kamal-backup 0.3.0.beta8 → 0.3.0.beta9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d920c58d8ff83794df465f0549d8599ea6a5e815b800221fa850ce024241abfa
4
- data.tar.gz: feb8374a19862349d1fb0b3d55e3e697b45df66d58fc0c0f63ddba4767ed01f9
3
+ metadata.gz: c7c67946461c23a767a12d31d82389bb4e0fb3c75a5494f102c4dad8facecb2e
4
+ data.tar.gz: f0265c16c92bdf291bf19f0586589af08938962c5a6b79635f782559dee75d39
5
5
  SHA512:
6
- metadata.gz: 9e36489f2557dca0695be87b779a9b20f96148b141e67a9422bc8933c925ea68a17a73d221c56f4a51585258194752f0db4f0b6fed4a4845783334e6dc0d8e0e
7
- data.tar.gz: f8bb63eb69f7da8bdfcc001e07c95495ac60fa6996eb4b4188cfb2a8bc453979176985703f897c8e5ac4a9b02faec5cf3d76aad15862b0c964d6c961c2910556
6
+ metadata.gz: f919b9df92d55407c57745e61cfa4fd011c15060ab6edd5d93b75516fef13b22f0490e7010531bb6c464578df6a25faf8a485d6a35f5431f9a6e53331cef90a5
7
+ data.tar.gz: d7243e236effb7c4da158c70993af8896e39764952f9dc2155a123655ddac49931804c67dd10424d10a5ddcdd0208542a28fe798256691a4cb2287ef35bba242
@@ -16,6 +16,8 @@ require_relative "schema"
16
16
 
17
17
  module KamalBackup
18
18
  class App
19
+ FRESH_BACKUP_GRACE_SECONDS = 5
20
+
19
21
  attr_reader :config, :redactor
20
22
 
21
23
  def initialize(env: ENV, config: nil, redactor: nil, restic: nil, database: nil, evidence_class: Evidence, scheduler_class: Scheduler)
@@ -28,6 +30,7 @@ module KamalBackup
28
30
  end
29
31
 
30
32
  def backup
33
+ started_at = Time.now.utc
31
34
  config.validate_backup
32
35
  require_restic!
33
36
 
@@ -43,7 +46,9 @@ module KamalBackup
43
46
  restic.check
44
47
  end
45
48
 
46
- true
49
+ backup_summary(started_at: started_at, finished_at: Time.now.utc).tap do |summary|
50
+ validate_fresh_backup_summary!(summary, started_at: started_at)
51
+ end
47
52
  end
48
53
 
49
54
  def validate(check_files: true)
@@ -241,6 +246,59 @@ module KamalBackup
241
246
  result[:files] = file_results.size == 1 ? file_results.first : file_results
242
247
  end
243
248
 
249
+ def backup_summary(started_at:, finished_at:)
250
+ {
251
+ kind: "backup_result",
252
+ status: "ok",
253
+ started_at: started_at.iso8601,
254
+ finished_at: finished_at.iso8601,
255
+ databases: databases.map { |adapter| backup_snapshot_summary(adapter) },
256
+ files: backup_file_snapshot_summary
257
+ }
258
+ end
259
+
260
+ def backup_snapshot_summary(adapter)
261
+ snapshot = restic.latest_snapshot(tags: database_snapshot_tags(adapter))
262
+ snapshot_summary(snapshot).merge(
263
+ database: database_config_name(adapter),
264
+ adapter: adapter.adapter_name
265
+ )
266
+ end
267
+
268
+ def backup_file_snapshot_summary
269
+ return nil if config.backup_paths.empty?
270
+
271
+ snapshot_summary(restic.latest_snapshot(tags: ["type:files"]))
272
+ end
273
+
274
+ def snapshot_summary(snapshot)
275
+ {
276
+ snapshot: snapshot && (snapshot["short_id"] || snapshot["id"]),
277
+ time: snapshot && snapshot["time"]
278
+ }
279
+ end
280
+
281
+ def validate_fresh_backup_summary!(summary, started_at:)
282
+ stale_databases = summary.fetch(:databases).reject { |entry| fresh_snapshot?(entry, started_at) }
283
+
284
+ unless stale_databases.empty?
285
+ names = stale_databases.map { |entry| entry.fetch(:database) }.join(", ")
286
+ raise ConfigurationError, "backup did not create a fresh database snapshot for #{names}"
287
+ end
288
+
289
+ files = summary[:files]
290
+ if files && !fresh_snapshot?(files, started_at)
291
+ raise ConfigurationError, "backup did not create a fresh file snapshot"
292
+ end
293
+ end
294
+
295
+ def fresh_snapshot?(entry, started_at)
296
+ snapshot_time = Time.parse(entry[:time].to_s)
297
+ snapshot_time >= started_at - FRESH_BACKUP_GRACE_SECONDS
298
+ rescue ArgumentError
299
+ false
300
+ end
301
+
244
302
  def database_snapshot_tags(adapter)
245
303
  ["type:database", "database:#{database_config_name(adapter)}", "adapter:#{adapter.adapter_name}"]
246
304
  end
@@ -138,6 +138,19 @@ module KamalBackup
138
138
  puts("fix: #{status_output.decorate(accessory_reboot_command, :yellow, :bold)}") if status == "out of sync"
139
139
  end
140
140
 
141
+ def print_backup_result(result)
142
+ return unless result.is_a?(Hash)
143
+
144
+ puts("Backup completed at #{result.fetch(:finished_at)}")
145
+ result.fetch(:databases).each do |database|
146
+ puts("database #{database.fetch(:database)}: #{database.fetch(:snapshot)} at #{database.fetch(:time)}")
147
+ end
148
+
149
+ if files = result[:files]
150
+ puts("files: #{files.fetch(:snapshot)} at #{files.fetch(:time)}")
151
+ end
152
+ end
153
+
141
154
  def validate_deploy_config
142
155
  config = Config.new(
143
156
  env: bridge.accessory_environment(accessory_name: accessory_name),
@@ -424,7 +437,7 @@ module KamalBackup
424
437
  if remote_command_mode?
425
438
  exec_remote(["kamal-backup", "backup"])
426
439
  else
427
- direct_app.backup
440
+ print_backup_result(direct_app.backup)
428
441
  end
429
442
  end
430
443
 
@@ -1,3 +1,3 @@
1
1
  module KamalBackup
2
- VERSION = "0.3.0.beta8"
2
+ VERSION = "0.3.0.beta9"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kamal-backup
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0.beta8
4
+ version: 0.3.0.beta9
5
5
  platform: ruby
6
6
  authors:
7
7
  - crmne