From 02b3d42e18ec9c12621d028cf56cde7dba6213b5 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) --- itamae.gemspec | 2 +- lib/itamae/resource/file.rb | 36 +++++++++++++++++++++++++++++ spec/integration/default_spec.rb | 12 +++++++++- spec/integration/recipes/default.rb | 5 ++++ 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/itamae.gemspec b/itamae.gemspec index 4c84ee34..7c27d832 100644 --- a/itamae.gemspec +++ b/itamae.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.add_runtime_dependency "thor" - spec.add_runtime_dependency "specinfra", [">= 2.37.0", "< 3.0.0"] + spec.add_runtime_dependency "specinfra", [">= 2.54.0", "< 3.0.0"] spec.add_runtime_dependency "hashie" spec.add_runtime_dependency "ansi" spec.add_runtime_dependency "schash", "~> 0.1.0" diff --git a/lib/itamae/resource/file.rb b/lib/itamae/resource/file.rb index 5c7b5d42..1612b149 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 @@ -58,6 +61,8 @@ def show_differences end def action_create(options) + backup if current.exist + if !current.exist && !@temppath run_command(["touch", attributes.path]) end @@ -84,6 +89,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 @@ -183,6 +190,35 @@ def send_tempfile f.unlink if f end end + + def backup + return if !attributes.backup || 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(:change_file_mode, backup_directory, '0777') + 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 a5286cff..4a36eb76 100644 --- a/spec/integration/default_spec.rb +++ b/spec/integration/default_spec.rb @@ -51,9 +51,19 @@ end end +describe file('/var/itamae/backup/tmp') do + it { should be_directory } + it { should be_mode 777 } +end + +describe command('cat /var/itamae/backup/tmp/file.itamae-*') do + its(:stdout) { should match(/Hello World/) } + its(:exit_status) { should eq(0) } +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 14323284..53c895e8 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