|
3 | 3 | module Itamae
|
4 | 4 | module Resource
|
5 | 5 | class File < Base
|
| 6 | + BACKUP_PATH = '/var/itamae/backup'.freeze |
| 7 | + |
6 | 8 | define_attribute :action, default: :create
|
7 | 9 | define_attribute :path, type: String, default_name: true
|
8 | 10 | define_attribute :content, type: String, default: nil
|
9 | 11 | define_attribute :mode, type: String
|
10 | 12 | define_attribute :owner, type: String
|
11 | 13 | define_attribute :group, type: String
|
| 14 | + define_attribute :backup, type: [FalseClass, Integer], default: 5 |
12 | 15 | define_attribute :block, type: Proc, default: proc {}
|
13 | 16 |
|
14 | 17 | def pre_action
|
@@ -56,6 +59,8 @@ def show_differences
|
56 | 59 | end
|
57 | 60 |
|
58 | 61 | def action_create(options)
|
| 62 | + backup if current.exist |
| 63 | + |
59 | 64 | if !current.exist && !@temppath
|
60 | 65 | run_command(["touch", attributes.path])
|
61 | 66 | end
|
@@ -93,6 +98,8 @@ def action_delete(options)
|
93 | 98 | end
|
94 | 99 |
|
95 | 100 | def action_edit(options)
|
| 101 | + backup if current.exist |
| 102 | + |
96 | 103 | if attributes.mode
|
97 | 104 | run_specinfra(:change_file_mode, @temppath, attributes.mode)
|
98 | 105 | else
|
@@ -171,6 +178,34 @@ def send_tempfile
|
171 | 178 | f.unlink if f
|
172 | 179 | end
|
173 | 180 | end
|
| 181 | + |
| 182 | + def backup |
| 183 | + return if !attributes.backup || attributes.backup <= 0 |
| 184 | + |
| 185 | + savetime = Time.now.strftime('%Y%m%d%H%M%S') |
| 186 | + backup_filename = "#{attributes.path}.itamae-#{savetime}" |
| 187 | + backup_path = ::File.join(BACKUP_PATH, backup_filename) |
| 188 | + backup_directory = ::File.dirname(backup_path) |
| 189 | + |
| 190 | + run_command(['install', '-d', '-m=777', backup_directory]) |
| 191 | + run_command(['cp', '-p', attributes.path, backup_path]) |
| 192 | + Itamae.logger.info "#{attributes.path} backed up to #{backup_path}" |
| 193 | + |
| 194 | + basename = ::File.basename(attributes.path) |
| 195 | + backup_files = run_command(['ls', '-1', backup_directory]) |
| 196 | + backup_files = backup_files.stdout.chomp.split("\n").select { |f| |
| 197 | + f.match(/\A#{basename}.itamae-[0-9]+\z/) |
| 198 | + }.reverse |
| 199 | + |
| 200 | + if backup_files.length > attributes.backup |
| 201 | + remainder = backup_files.slice(attributes.backup..-1) |
| 202 | + remainder.each do |backup_to_delete| |
| 203 | + backup_to_delete = ::File.join(backup_directory, backup_to_delete) |
| 204 | + run_specinfra(:remove_file, backup_to_delete) |
| 205 | + Itamae.logger.info "#{attributes.path} removed backup at #{backup_to_delete}" |
| 206 | + end |
| 207 | + end |
| 208 | + end |
174 | 209 | end
|
175 | 210 | end
|
176 | 211 | end
|
0 commit comments