|
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
|
@@ -91,6 +96,8 @@ def action_delete(options)
|
91 | 96 | end
|
92 | 97 |
|
93 | 98 | def action_edit(options)
|
| 99 | + backup if current.exist |
| 100 | + |
94 | 101 | if attributes.mode
|
95 | 102 | run_specinfra(:change_file_mode, @temppath, attributes.mode)
|
96 | 103 | else
|
@@ -169,6 +176,34 @@ def send_tempfile
|
169 | 176 | f.unlink if f
|
170 | 177 | end
|
171 | 178 | end
|
| 179 | + |
| 180 | + def backup |
| 181 | + return unless (attributes.backup).kind_of?(FalseClass) ? false : attributes.backup > 0 |
| 182 | + |
| 183 | + savetime = Time.now.strftime('%Y%m%d%H%M%S') |
| 184 | + backup_filename = "#{attributes.path}.itamae-#{savetime}" |
| 185 | + backup_path = ::File.join(BACKUP_PATH, backup_filename) |
| 186 | + backup_directory = ::File.dirname(backup_path) |
| 187 | + |
| 188 | + run_specinfra(:create_file_as_directory, backup_directory) |
| 189 | + run_specinfra(:copy_file, attributes.path, backup_path) |
| 190 | + Itamae.logger.info "#{attributes.path} backed up to #{backup_path}" |
| 191 | + |
| 192 | + basename = ::File.basename(attributes.path) |
| 193 | + backup_files = run_command(['ls', '-1', backup_directory]) |
| 194 | + backup_files = backup_files.stdout.chomp.split("\n").select { |f| |
| 195 | + f.match(/\A#{basename}.itamae-[0-9]+\z/) |
| 196 | + }.reverse |
| 197 | + |
| 198 | + if backup_files.length > attributes.backup |
| 199 | + remainder = backup_files.slice(attributes.backup..-1) |
| 200 | + remainder.each do |backup_to_delete| |
| 201 | + backup_to_delete = ::File.join(backup_directory, backup_to_delete) |
| 202 | + run_specinfra(:remove_file, backup_to_delete) |
| 203 | + Itamae.logger.info "#{attributes.path} removed backup at #{backup_to_delete}" |
| 204 | + end |
| 205 | + end |
| 206 | + end |
172 | 207 | end
|
173 | 208 | end
|
174 | 209 | end
|
0 commit comments