From af1e2d09c3208b4c4c5c0bd952bc6667888533a2 Mon Sep 17 00:00:00 2001 From: Akihiko Horiuchi <12ff5b8@gmail.com> Date: Thu, 14 Jan 2016 00:08:06 +0900 Subject: [PATCH] Add backup attribute to file resource (close #124) --- lib/itamae/resource/file.rb | 35 +++++++++++++++++++++++++++++ spec/integration/default_spec.rb | 6 ++++- spec/integration/recipes/default.rb | 5 +++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/lib/itamae/resource/file.rb b/lib/itamae/resource/file.rb index 9fc253f4..56cb2bb7 100644 --- a/lib/itamae/resource/file.rb +++ b/lib/itamae/resource/file.rb @@ -3,12 +3,15 @@ module Itamae module Resource class File < Base + BACKUP_PATH = '/var/itamae/backup'.freeze + define_attribute :action, default: :create define_attribute :path, type: String, default_name: true define_attribute :content, type: String, default: nil define_attribute :mode, type: String define_attribute :owner, type: String define_attribute :group, type: String + define_attribute :backup, type: [FalseClass, Integer], default: 5 define_attribute :block, type: Proc, default: proc {} def pre_action @@ -56,6 +59,8 @@ def show_differences end def action_create(options) + backup if current.exist + if !current.exist && !@temppath run_command(["touch", attributes.path]) end @@ -91,6 +96,8 @@ def action_delete(options) end def action_edit(options) + backup if current.exist + if attributes.mode run_specinfra(:change_file_mode, @temppath, attributes.mode) else @@ -169,6 +176,34 @@ def send_tempfile f.unlink if f end end + + def backup + return unless (attributes.backup).kind_of?(FalseClass) ? false : attributes.backup > 0 + + savetime = Time.now.strftime('%Y%m%d%H%M%S') + backup_filename = "#{attributes.path}.itamae-#{savetime}" + backup_path = ::File.join(BACKUP_PATH, backup_filename) + backup_directory = ::File.dirname(backup_path) + + run_specinfra(:create_file_as_directory, backup_directory) + run_specinfra(:copy_file, attributes.path, backup_path) + Itamae.logger.info "#{attributes.path} backed up to #{backup_path}" + + basename = ::File.basename(attributes.path) + backup_files = run_command(['ls', '-1', backup_directory]) + backup_files = backup_files.stdout.chomp.split("\n").select { |f| + f.match(/\A#{basename}.itamae-[0-9]+\z/) + }.reverse + + if backup_files.length > attributes.backup + remainder = backup_files.slice(attributes.backup..-1) + remainder.each do |backup_to_delete| + backup_to_delete = ::File.join(backup_directory, backup_to_delete) + run_specinfra(:remove_file, backup_to_delete) + Itamae.logger.info "#{attributes.path} removed backup at #{backup_to_delete}" + end + end + end end end end diff --git a/spec/integration/default_spec.rb b/spec/integration/default_spec.rb index 800fe229..a4b80a86 100644 --- a/spec/integration/default_spec.rb +++ b/spec/integration/default_spec.rb @@ -51,9 +51,13 @@ end end +describe file('/var/itamae/backup/tmp') do + it { should be_directory } +end + describe file('/tmp/file') do it { should be_file } - its(:content) { should match(/Hello World/) } + its(:content) { should match(/Hello New World/) } it { should be_mode 777 } end diff --git a/spec/integration/recipes/default.rb b/spec/integration/recipes/default.rb index 432ad7cc..342c3e6e 100644 --- a/spec/integration/recipes/default.rb +++ b/spec/integration/recipes/default.rb @@ -148,6 +148,11 @@ mode "777" end +file "/tmp/file" do + content "Hello New World" + mode "777" +end + execute "echo 'Hello Execute' > /tmp/execute" file "/tmp/never_exist1" do