Rex

 view release on metacpan or  search on metacpan

lib/Rex/Commands/File.pm  view on Meta::CPAN


  elsif ( ( exists $option->{content} || exists $option->{source} )
    && !$is_directory )
  {

    # first upload file to tmp location, to get md5 sum.
    # than we can decide if we need to replace the current (old) file.

    my $tmp_file_name = get_tmp_file_name($file);

    if ( exists $option->{content} ) {
      my $fh    = file_write($tmp_file_name);
      my @lines = split( qr{$/}, $option->{"content"} );
      for my $line (@lines) {
        $fh->write( $line . $/ );
      }
      $fh->close;
    }
    elsif ( exists $option->{source} ) {
      $option->{source} =
        Rex::Helper::Path::get_file_path( $option->{source}, caller );

      upload $option->{source}, $tmp_file_name;
    }

    # now get md5 sums
    eval { $old_md5 = md5($file); };
    $new_md5 = md5($tmp_file_name);

    if ( $new_md5 && $old_md5 && $new_md5 eq $old_md5 ) {
      Rex::Logger::debug(
        "No need to overwrite existing file. Old and new files are the same. $old_md5 eq $new_md5."
      );

      # md5 sums are the same, delete tmp.
      $fs->unlink($tmp_file_name);
      $need_md5 = 0; # we don't need to execute on_change hook

      Rex::get_current_connection()->{reporter}->report(
        changed => 0,
        message =>
          "No need to overwrite existing file. Old and new files are the same. $old_md5 eq $new_md5."
      );
    }
    else {
      $old_md5 ||= "";
      Rex::Logger::debug(
        "Need to use the new file. md5 sums are different. <<$old_md5>> = <<$new_md5>>"
      );

      #### check and run before_change hook
      Rex::Hook::run_hook( file => "before_change", $file, %{$option} );
      ##############################

      if (Rex::is_sudo) {
        my $current_options =
          Rex::get_current_connection_object()->get_current_sudo_options;
        Rex::get_current_connection_object()->push_sudo_options( {} );

        if ( exists $current_options->{user} ) {
          $fs->chown( "$current_options->{user}:", $tmp_file_name );
        }
      }

      $fs->rename( $tmp_file_name, $file );
      Rex::get_current_connection_object()->pop_sudo_options()
        if (Rex::is_sudo);

      $__ret = { changed => 1 };

      Rex::get_current_connection()->{reporter}->report(
        changed => 1,
        message => "File updated. old md5: $old_md5, new md5: $new_md5"
      );

      #### check and run after_change hook
      Rex::Hook::run_hook( file => "after_change", $file, %{$option}, $__ret );
      ##############################

    }

  }

  if ( exists $option->{"ensure"} ) {
    if ( $option->{ensure} eq "present" ) {
      if ( !$fs->is_file($file) ) {

        #### check and run before_change hook
        Rex::Hook::run_hook( file => "before_change", $file, %{$option} );
        ##############################

        my $fh = file_write($file);
        $fh->write("");
        $fh->close;
        $__ret = { changed => 1 };

        Rex::get_current_connection()->{reporter}->report(
          changed => 1,
          message => "file is now present, with no content",
        );

        #### check and run after_change hook
        Rex::Hook::run_hook(
          file => "after_change",
          $file, %{$option}, $__ret
        );
        ##############################

      }
      elsif ( !$__ret->{changed} ) {
        $__ret = { changed => 0 };
        Rex::get_current_connection()->{reporter}->report( changed => 0, );
      }
    }
    elsif ( $option->{ensure} eq "absent" ) {
      $need_md5 = 0;

      #### check and run before_change hook
      Rex::Hook::run_hook( file => "before_change", $file, %{$option} );
      ##############################

lib/Rex/Commands/File.pm  view on Meta::CPAN

      if ( exists $option->{group} ) {
        $dir_option{group} = $option->{group};
      }
      if ( exists $option->{mode} ) {
        $dir_option{mode} = $option->{mode};
      }

      Rex::Commands::Fs::mkdir( $file, %dir_option, on_change => $on_change );
    }
  }

  if ( !exists $option->{content}
    && !exists $option->{source}
    && $option->{ensure} ne "absent" )
  {

    # no content and no source, so just verify that the file is present
    if ( !$fs->is_file($file) && !$is_directory ) {

      #### check and run before_change hook
      Rex::Hook::run_hook( file => "before_change", $file, %{$option} );
      ##############################

      my $fh = file_write($file);
      $fh->write("");
      $fh->close;

      my $f_type = "file is now present, with no content";
      if ( exists $option->{ensure} && $option->{ensure} eq "directory" ) {
        $f_type = "directory is now present";
      }

      Rex::get_current_connection()->{reporter}->report(
        changed => 1,
        message => $f_type,
      );

      #### check and run after_change hook
      Rex::Hook::run_hook( file => "after_change", $file, %{$option}, $__ret );
      ##############################

    }
  }

  if ( $option->{ensure} ne "absent" ) {

    if ($need_md5) {
      eval { $new_md5 = md5($file); };
    }
    my %stat_old = $fs->stat($file);

    if ( exists $option->{"mode"} ) {
      $fs->chmod( $option->{"mode"}, $file );
    }

    if ( exists $option->{"group"} ) {
      $fs->chgrp( $option->{"group"}, $file );
    }

    if ( exists $option->{"owner"} ) {
      $fs->chown( $option->{"owner"}, $file );
    }

    my %stat_new = $fs->stat($file);

    if ( %stat_old && %stat_new && $stat_old{mode} ne $stat_new{mode} ) {
      Rex::get_current_connection()->{reporter}->report(
        changed => 1,
        message =>
          "File-System permissions changed from $stat_old{mode} to $stat_new{mode}.",
      );
    }

    if ( %stat_old && %stat_new && $stat_old{uid} ne $stat_new{uid} ) {
      Rex::get_current_connection()->{reporter}->report(
        changed => 1,
        message => "Owner changed from $stat_old{uid} to $stat_new{uid}.",
      );
    }

    if ( %stat_old && %stat_new && $stat_old{gid} ne $stat_new{gid} ) {
      Rex::get_current_connection()->{reporter}->report(
        changed => 1,
        message => "Group changed from $stat_old{gid} to $stat_new{gid}.",
      );
    }

  }

  my $on_change_done = 0;

  if ($need_md5) {
    unless ( $old_md5 && $new_md5 && $old_md5 eq $new_md5 ) {
      $old_md5 ||= "";
      $new_md5 ||= "";

      Rex::Logger::debug("File $file has been changed... Running on_change");
      Rex::Logger::debug("old: $old_md5");
      Rex::Logger::debug("new: $new_md5");

      &$on_change($file);

      $on_change_done = 1;

      Rex::get_current_connection()->{reporter}->report(
        changed => 1,
        message => "Content changed.",
      );

      $__ret = { changed => 1 };
    }
  }

  if ( $__ret->{changed} == 1 && $on_change_done == 0 ) {
    &$on_change($file);
  }
  elsif ( $__ret->{changed} == 0 ) {
    Rex::Logger::debug(
      "File $file has not been changed... Running on_no_change");
    &$on_no_change($file);
  }

lib/Rex/Commands/File.pm  view on Meta::CPAN

=cut

sub extract {
  my ( $file, %option ) = @_;
  $file = resolv_path($file);

  my $pre_cmd = "";
  my $to      = ".";
  my $type    = "";

  if ( $option{chdir} ) {
    $to = $option{chdir};
  }

  if ( $option{to} ) {
    $to = $option{to};
  }
  $to = resolv_path($to);

  if ( $option{type} ) {
    $type = $option{type};
  }

  Rex::Commands::Fs::mkdir($to);
  $pre_cmd = "cd $to; ";

  my $exec = Rex::Interface::Exec->create;
  my $cmd  = "";

  if ( $type eq 'tgz'
    || $file =~ m/\.tar\.gz$/
    || $file =~ m/\.tgz$/
    || $file =~ m/\.tar\.Z$/ )
  {
    $cmd = "${pre_cmd}gunzip -c $file | tar -xf -";
  }
  elsif ( $type eq 'tbz' || $file =~ m/\.tar\.bz2/ || $file =~ m/\.tbz2/ ) {
    $cmd = "${pre_cmd}bunzip2 -c $file | tar -xf -";
  }
  elsif ( $type eq 'tar' || $file =~ m/\.(tar|box)/ ) {
    $cmd = "${pre_cmd}tar -xf $file";
  }
  elsif ( $type eq 'zip' || $file =~ m/\.(zip|war|jar)$/ ) {
    $cmd = "${pre_cmd}unzip -o $file";
  }
  elsif ( $type eq 'gz' || $file =~ m/\.gz$/ ) {
    $cmd = "${pre_cmd}gunzip -f $file";
  }
  elsif ( $type eq 'bz2' || $file =~ m/\.bz2$/ ) {
    $cmd = "${pre_cmd}bunzip2 -f $file";
  }
  else {
    Rex::Logger::info("File not supported.");
    die("File ($file) not supported.");
  }

  $exec->exec($cmd);

  my $fs = Rex::Interface::Fs->create;
  if ( $option{owner} ) {
    $fs->chown( $option{owner}, $to, recursive => 1 );
  }

  if ( $option{group} ) {
    $fs->chgrp( $option{group}, $to, recursive => 1 );
  }

  if ( $option{mode} ) {
    $fs->chmod( $option{mode}, $to, recursive => 1 );
  }

}

=head2 sed($search, $replace, $file [, %options])

Search some string in a file and replace it.

 task sar => sub {
   # this will work line by line
   sed qr{search}, "replace", "/var/log/auth.log";

   # to use it in a multiline way
   sed qr{search}, "replace", "/var/log/auth.log",
    multiline => TRUE;
 };

Like similar file management commands, it also supports C<on_change> and C<on_no_change> hooks.

=cut

sub sed {
  my ( $search, $replace, $file, @option ) = @_;
  $file = resolv_path($file);
  my $options = {};

  Rex::get_current_connection()->{reporter}
    ->report_resource_start( type => "sed", name => $file );

  if ( ref( $option[0] ) ) {
    $options = $option[0];
  }
  else {
    $options = {@option};
  }

  my $on_change    = $options->{"on_change"}    || undef;
  my $on_no_change = $options->{"on_no_change"} || undef;

  my @content;

  if ( exists $options->{multiline} ) {
    $content[0] = cat($file);
    $content[0] =~ s/$search/$replace/gms;
  }
  else {
    @content = split( /\n/, cat($file) );
    for (@content) {
      s/$search/$replace/;
    }
  }



( run in 0.914 second using v1.01-cache-2.11-cpan-5511b514fd6 )