diff --git a/lib/itamae/resource/file.rb b/lib/itamae/resource/file.rb index 9fc253f4..6c5cf6c0 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') + basename = ::File.basename(attributes.path) + backup_filename = "#{basename}.itamae-#{savetime}" + backup_path = ::File.join(BACKUP_PATH, backup_filename) + + run_specinfra(:create_file_as_directory, ::File.dirname(backup_path)) + run_specinfra(:copy_file, attributes.path, backup_path) + Itamae.logger.info "#{attributes.path} backed up to #{backup_path}" + + backup_files = run_command(['ls', '-1', BACKUP_PATH]) + backup_files = backup_files.stdout.chomp.split("\n").select { |f| + f.match("#{basename}.itamae-") + }.sort { |a, b| + b <=> a + } + + if backup_files.length > attributes.backup + remainder = backup_files.slice(attributes.backup..-1) + remainder.each do |backup_to_delete| + run_specinfra(:remove_file, ::File.join(BACKUP_PATH, backup_to_delete)) + Itamae.logger.info "#{attributes.path} removed backup at #{backup_path}" + end + end + end end end end diff --git a/spec/integration/default_spec.rb b/spec/integration/default_spec.rb index 800fe229..513dc9a4 100644 --- a/spec/integration/default_spec.rb +++ b/spec/integration/default_spec.rb @@ -51,9 +51,13 @@ end end +describe file('/var/itamae/backup') 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