lib/do_snapshot/cli.rb
# -*- encoding : utf-8 -*-
# frozen_string_literal: true
require 'thor'
require 'do_snapshot'
require_relative 'log'
require_relative 'mail'
require_relative 'helpers'
require_relative 'command'
module DoSnapshot
# CLI is here
#
class CLI < Thor # rubocop:disable ClassLength
include DoSnapshot::Helpers
default_task :snap
map %w( c s create ) => :snap
map %w( -V ) => :version
# Overriding Thor method for custom initialization
#
def initialize(*args)
super
setup_config
set_logger
set_mailer
# Check for keys via options
%w( digital_ocean_access_token ).each do |key|
ENV[key.upcase] = options[key] if options.include? key
end
end
desc 'c / s / snap / create', 'DEFAULT. Create and cleanup snapshot\'s'
long_desc <<-LONGDESC
`do_snapshot` able to create and cleanup snapshots on your droplets.
You can optionally specify parameters to select or exclude some droplets.
### Examples
Select api version (2):
$ do_snapshot -p 2
Set DigitalOcean keys:
$ do_snapshot --digital_ocean_api_token SOMELONGTOKEN
Keep latest 5 and cleanup older if maximum is reached, verbose:
$ do_snapshot -k 5 -c -v
Keep latest 3 from selected droplet:
$ do_snapshot --only 123456 --keep 3
Working with all except selected droplets:
$ do_snapshot --exclude 123456 123457
Keep latest 5 snapshots, not create new if we have more, send mail notification instead:
$ do_snapshot --keep 10 --stop --mail to:yourmail@example.com
### Cron example
0 4 * * 7 /.../bin/do_snapshot -k 5 -m to:TO from:FROM -t address:HOST user_name:LOGIN password:PASSWORD port:2525 -q -c
### Advanced options example for MAIL feature:
--mail to:mail@somehost.com from:from@host.com --smtp address:smtp.gmail.com port:25 user_name:someuser password:somepassword
For more details look here: https://github.com/benprew/pony
VERSION: #{DoSnapshot::VERSION}
LONGDESC
method_option :protocol,
type: :numeric,
default: 2,
aliases: %w( -p ),
banner: '1',
desc: 'Select api version.'
method_option :shutdown,
default: false,
type: :boolean,
desc: 'Check if you want to stop droplet before the snapshot.'
method_option :only,
type: :array,
default: [],
aliases: %w( -o ),
banner: '123456 123456 123456',
desc: 'Select some droplets.'
method_option :exclude,
type: :array,
default: [],
aliases: %w( -e ),
banner: '123456 123456 123456',
desc: 'Except some droplets.'
method_option :keep,
type: :numeric,
default: 10,
aliases: %w( -k ),
banner: '5',
desc: 'How much snapshots you want to keep?'
method_option :delay,
type: :numeric,
default: 10,
aliases: %w( -d ),
banner: '5',
desc: 'Delay between snapshot operation status requests.'
method_option :timeout,
type: :numeric,
default: 3600,
banner: '250',
desc: 'Timeout in sec\'s for events like Power Off or Create Snapshot.'
method_option :mail,
type: :hash,
aliases: %w( -m ),
banner: 'to:yourmail@example.com',
desc: 'Receive mail if fail or maximum is reached.'
method_option :smtp,
type: :hash,
aliases: %w( -t ),
banner: 'user_name:yourmail@example.com password:password',
desc: 'SMTP options.'
method_option :log,
type: :string,
aliases: %w( -l ),
banner: '/Users/someone/.do_snapshot/main.log',
desc: 'Log file path. By default logging is disabled.'
method_option :clean,
default: true,
type: :boolean,
aliases: %w( -c ),
desc: 'Cleanup snapshots after create. If you have more images than you want to `keep`, older will be deleted.'
method_option :stop,
type: :boolean,
aliases: %w( -s),
desc: 'Stop creating snapshots if maximum is reached.'
method_option :stop_by_power,
type: :boolean,
desc: "Droplet stop method, by it's power status (instead of waiting for event completed state)."
method_option :trace,
type: :boolean,
aliases: %w( -v ),
desc: 'Verbose mode.'
method_option :quiet,
type: :boolean,
aliases: %w( -q ),
desc: 'Quiet mode. If don\'t need any messages and in console.'
method_option :digital_ocean_access_token,
type: :string,
banner: 'YOURLONGAPITOKEN',
desc: 'DIGITAL_OCEAN_ACCESS_TOKEN. if you can\'t use environment.'
def snap
command.snap
rescue DoSnapshot::NoTokenError, DoSnapshot::NoKeysError => e
error_simple(e)
rescue => e
command.fail_power_off(e) if [SnapshotCreateError, DropletShutdownError].include?(e.class)
error_with_backtrace(e)
end
desc 'version, -V', 'Shows the version of the currently installed DoSnapshot gem'
def version
puts DoSnapshot::VERSION
end
no_commands do
def error_simple(e)
logger.error e.message
send_error
fail e
end
def error_with_backtrace(e)
logger.error e.message
backtrace(e) if options.include? 'trace'
send_error
fail e
end
def command
@command ||= Command.new(options, command_filter)
end
def update_command
command.load_options(options, command_filter)
end
def command_filter
%w( log smtp mail trace digital_ocean_access_token )
end
def setup_config # rubocop:disable Metrics/AbcSize
DoSnapshot.configure do |config|
config.logger = ::Logger.new(options['log']) if options['log']
config.logger_level = Logger::DEBUG if config.verbose
config.verbose = options['trace']
config.quiet = options['quiet']
config.mailer = Mail.new(opts: options['mail'], smtp: options['smtp']) if options['mail']
end
end
def set_mailer
DoSnapshot.mailer = DoSnapshot.config.mailer
end
def send_error
return unless DoSnapshot.mailer.respond_to?(:opts)
DoSnapshot.mailer.opts[:subject] = 'Digital Ocean: Error.'
DoSnapshot.mailer.opts[:body] = 'Please check your droplets.'
mailer.notify
end
def set_logger
DoSnapshot.logger = Log.new(shell: shell)
end
def backtrace(e)
e.backtrace.each do |t|
logger.error t
end
end
end
end
end