feat(backup-monitor): implement BackupNotifier and CLI entry point
This commit is contained in:
parent
3e49704bdb
commit
765ffd2394
|
|
@ -115,8 +115,49 @@ class WebhookClient
|
|||
end
|
||||
|
||||
class BackupNotifier
|
||||
def initialize(options:, client:)
|
||||
@options = options
|
||||
@client = client
|
||||
end
|
||||
|
||||
def self.from_env(options)
|
||||
url = ENV.fetch('N8N_SWANSONCLOUD_URL')
|
||||
token = ENV.fetch('N8N_SWANSONCLOUD_BACKUP_AUTH_TOKEN')
|
||||
new(options: options, client: WebhookClient.new(base_url: url, auth_token: token))
|
||||
end
|
||||
|
||||
def notify
|
||||
payload = PayloadBuilder.new(@options).build
|
||||
@client.post(payload)
|
||||
end
|
||||
end
|
||||
|
||||
if __FILE__ == $PROGRAM_NAME
|
||||
# CLI entry point — implemented in Task 5
|
||||
options = {}
|
||||
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = 'Usage: notify_backup.rb [options]'
|
||||
opts.separator ''
|
||||
opts.separator 'Required:'
|
||||
opts.on('--machine NAME', 'Host identifier (e.g. desktop, vps-ovh-prod-01)') { |v| options[:machine] = v }
|
||||
opts.on('--destination NAME', 'Backup destination (e.g. synology, backblaze-b2)') { |v| options[:destination] = v }
|
||||
opts.on('--status STATUS', 'success | failure | skipped') { |v| options[:status] = v }
|
||||
opts.separator ''
|
||||
opts.separator 'Optional:'
|
||||
opts.on('--bytes N', Integer, 'Raw bytes transferred (formatted before sending)') { |v| options[:bytes] = v }
|
||||
opts.on('--snapshot ID', 'Snapshot ID (e.g. restic snapshot hash)') { |v| options[:snapshot] = v }
|
||||
opts.on('--log-path PATH', 'Path to the backup log for this run') { |v| options[:log_path] = v }
|
||||
opts.on('--notes TEXT', 'Free-form output: restic tail, skip reason, etc.') { |v| options[:notes] = v }
|
||||
end.parse!
|
||||
|
||||
%i[machine destination status].each do |required|
|
||||
abort "Error: --#{required} is required. Run with --help for usage." unless options[required]
|
||||
end
|
||||
|
||||
begin
|
||||
BackupNotifier.from_env(options).notify
|
||||
rescue => e
|
||||
warn "notify_backup: failed to send webhook: #{e.message}"
|
||||
exit 0
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -136,3 +136,54 @@ class WebhookClientTest < Minitest::Test
|
|||
assert_match(/HTTP 500/, err.message)
|
||||
end
|
||||
end
|
||||
|
||||
class FakeClient
|
||||
def initialize
|
||||
@posted = false
|
||||
@payload = nil
|
||||
end
|
||||
|
||||
def post(payload)
|
||||
@posted = true
|
||||
@payload = payload
|
||||
end
|
||||
|
||||
def posted_payload
|
||||
@payload
|
||||
end
|
||||
|
||||
def was_called?
|
||||
@posted
|
||||
end
|
||||
end
|
||||
|
||||
class BackupNotifierTest < Minitest::Test
|
||||
def base_options
|
||||
{ machine: 'desktop', destination: 'synology', status: 'success' }
|
||||
end
|
||||
|
||||
def test_notify_calls_client_with_a_hash_payload
|
||||
fake_client = FakeClient.new
|
||||
|
||||
BackupNotifier.new(options: base_options, client: fake_client).notify
|
||||
|
||||
assert fake_client.was_called?
|
||||
assert_instance_of Hash, fake_client.posted_payload
|
||||
end
|
||||
|
||||
def test_from_env_returns_a_backup_notifier
|
||||
ENV['N8N_SWANSONCLOUD_URL'] = 'https://n8n.example.com'
|
||||
ENV['N8N_SWANSONCLOUD_BACKUP_AUTH_TOKEN'] = 'test-token'
|
||||
|
||||
notifier = BackupNotifier.from_env(base_options)
|
||||
assert_instance_of BackupNotifier, notifier
|
||||
ensure
|
||||
ENV.delete('N8N_SWANSONCLOUD_URL')
|
||||
ENV.delete('N8N_SWANSONCLOUD_BACKUP_AUTH_TOKEN')
|
||||
end
|
||||
|
||||
def test_from_env_raises_when_env_var_missing
|
||||
ENV.delete('N8N_SWANSONCLOUD_URL')
|
||||
assert_raises(KeyError) { BackupNotifier.from_env(base_options) }
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue