33module Itamae
44 module Resource
55 class File < Base
6+ BACKUP_PATH = '/var/itamae/backup' . freeze
7+
68 define_attribute :action , default : :create
79 define_attribute :path , type : String , default_name : true
810 define_attribute :content , type : String , default : nil
911 define_attribute :mode , type : String
1012 define_attribute :owner , type : String
1113 define_attribute :group , type : String
14+ define_attribute :backup , type : [ FalseClass , Integer ] , default : 5
1215 define_attribute :block , type : Proc , default : proc { }
1316
1417 def pre_action
@@ -58,6 +61,8 @@ def show_differences
5861 end
5962
6063 def action_create ( options )
64+ backup if current . exist
65+
6166 if !current . exist && !@temppath
6267 run_command ( [ "touch" , attributes . path ] )
6368 end
@@ -84,6 +89,8 @@ def action_delete(options)
8489 end
8590
8691 def action_edit ( options )
92+ backup if current . exist
93+
8794 if attributes . mode
8895 run_specinfra ( :change_file_mode , @temppath , attributes . mode )
8996 else
@@ -183,6 +190,35 @@ def send_tempfile
183190 f . unlink if f
184191 end
185192 end
193+
194+ def backup
195+ return if !attributes . backup || attributes . backup <= 0
196+
197+ savetime = Time . now . strftime ( '%Y%m%d%H%M%S' )
198+ backup_filename = "#{ attributes . path } .itamae-#{ savetime } "
199+ backup_path = ::File . join ( BACKUP_PATH , backup_filename )
200+ backup_directory = ::File . dirname ( backup_path )
201+
202+ run_specinfra ( :create_file_as_directory , backup_directory )
203+ run_specinfra ( :change_file_mode , backup_directory , '0777' )
204+ run_specinfra ( :copy_file , attributes . path , backup_path )
205+ Itamae . logger . info "#{ attributes . path } backed up to #{ backup_path } "
206+
207+ basename = ::File . basename ( attributes . path )
208+ backup_files = run_command ( [ 'ls' , '-1' , backup_directory ] )
209+ backup_files = backup_files . stdout . chomp . split ( "\n " ) . select { |f |
210+ f . match ( /\A #{ basename } .itamae-[0-9]+\z / )
211+ } . reverse
212+
213+ if backup_files . length > attributes . backup
214+ remainder = backup_files . slice ( attributes . backup ..-1 )
215+ remainder . each do |backup_to_delete |
216+ backup_to_delete = ::File . join ( backup_directory , backup_to_delete )
217+ run_specinfra ( :remove_file , backup_to_delete )
218+ Itamae . logger . info "#{ attributes . path } removed backup at #{ backup_to_delete } "
219+ end
220+ end
221+ end
186222 end
187223 end
188224end
0 commit comments