do_snapshot 0.0.15 → 0.2.2

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
  SHA1:
3
- metadata.gz: daa05c7961b1c4dbf9275fb6242817289a52f9c8
4
- data.tar.gz: fc001ff0e7c71e660220972f9494106d1293e162
3
+ metadata.gz: 25e673a7db69593b0007d27f55f873b12b2efad6
4
+ data.tar.gz: 159359c4f15b5a85163b660b84e994c742f3cccd
5
5
  SHA512:
6
- metadata.gz: a1fd3c4e7b308883ffd689aadfaed8cc45295879ad471636ce0735e63f3e426387caca44ed110f5de6fc3190871f953c11cafd27121e45038c4bf7aa51bd1dc1
7
- data.tar.gz: 754e0414a459cc7125ca7991068cde13f3e12cfe82adbd8c07ad62f9d07ab6cd662c1a5a2a794b1320993d3fee816813163548304e5dd268767e2625a606cf52
6
+ metadata.gz: bb017632d9bdcff73d39310c7d5754fd0579f3975d23f6e16824797e3cf2afc7dfeeb041d645db05df370e1dd45b37842b4150d0f02d5e9158a8577d8e51c566
7
+ data.tar.gz: 1ef277c08b234bc7925d9e797c85c1e3179d475512ee8debe4159bc4ec818ac274e596e30643f7c2551e92f46451ff5f9d748f86a3113e1ada5766084af401c0
@@ -6,10 +6,11 @@ module DoSnapshot
6
6
  # Operating with Digital Ocean.
7
7
  #
8
8
  class Abstract
9
- attr_accessor :delay
10
- attr_accessor :timeout
9
+ include DoSnapshot::Log
11
10
 
12
- def initialize(options)
11
+ attr_accessor :delay, :timeout
12
+
13
+ def initialize(options = {})
13
14
  check_keys
14
15
  set_id
15
16
  options.each_pair do |key, option|
@@ -25,18 +26,18 @@ module DoSnapshot
25
26
 
26
27
  # Waiting for event exit
27
28
  def wait_event(id)
28
- Log.debug "Event Id: #{id}"
29
+ log.debug "Event Id: #{id}"
29
30
  time = Time.now
30
31
  sleep(delay) until get_event_status(id, time)
31
32
  end
32
33
 
33
34
  def after_cleanup(droplet_id, droplet_name, snapshot, event)
34
35
  if !event
35
- Log.error "Destroy of snapshot #{snapshot.name} for droplet id: #{droplet_id} name: #{droplet_name} is failed."
36
+ log.error "Destroy of snapshot #{snapshot.name} for droplet id: #{droplet_id} name: #{droplet_name} is failed."
36
37
  elsif event && !event.status.include?('OK')
37
- Log.error event.message
38
+ log.error event.message
38
39
  else
39
- Log.debug "Snapshot name: #{snapshot.name} delete requested."
40
+ log.debug "Snapshot name: #{snapshot.name} delete requested."
40
41
  end
41
42
  end
42
43
  end
@@ -36,7 +36,7 @@ module DoSnapshot
36
36
  instance = droplet(id)
37
37
 
38
38
  if instance.status.include? 'active'
39
- Log.error 'Droplet is still running.'
39
+ log.error 'Droplet is still running.'
40
40
  else
41
41
  power_on id
42
42
  end
@@ -74,7 +74,7 @@ module DoSnapshot
74
74
 
75
75
  # Cleanup our snapshots.
76
76
  #
77
- def cleanup_snapshots(instance, size) # rubocop:disable MethodLength
77
+ def cleanup_snapshots(instance, size)
78
78
  (0..size).each do |i|
79
79
  # noinspection RubyResolve
80
80
  snapshot = instance.snapshots[i]
@@ -85,9 +85,9 @@ module DoSnapshot
85
85
  end
86
86
 
87
87
  def check_keys
88
- Log.debug 'Checking DigitalOcean Id\'s.'
88
+ log.debug 'Checking DigitalOcean Id\'s.'
89
89
  %w( DIGITAL_OCEAN_CLIENT_ID DIGITAL_OCEAN_API_KEY ).each do |key|
90
- Log.error "You must have #{key} in environment or set it via options." if ENV[key].blank?
90
+ log.error "You must have #{key} in environment or set it via options." if ENV[key].blank?
91
91
  end
92
92
  end
93
93
 
@@ -96,7 +96,7 @@ module DoSnapshot
96
96
  # Set id's of Digital Ocean API.
97
97
  #
98
98
  def set_id
99
- Log.debug 'Setting DigitalOcean Id\'s.'
99
+ log.debug 'Setting DigitalOcean Id\'s.'
100
100
  ::DigitaloceanC.client_id = ENV['DIGITAL_OCEAN_CLIENT_ID']
101
101
  ::DigitaloceanC.api_key = ENV['DIGITAL_OCEAN_API_KEY']
102
102
  end
@@ -105,10 +105,7 @@ module DoSnapshot
105
105
  # Before snapshot we to know that machine has powered off.
106
106
  #
107
107
  def get_event_status(id, time)
108
- if (Time.now - time) > @timeout
109
- Log.debug "Event #{id} finished by timeout #{time}"
110
- return true
111
- end
108
+ return true if timeout?(id, time)
112
109
 
113
110
  event = ::DigitaloceanC::Event.find(id)
114
111
  fail event.message unless event.status.include?('OK')
@@ -116,6 +113,12 @@ module DoSnapshot
116
113
  event.event.percentage && event.event.percentage.include?('100') ? true : false
117
114
  end
118
115
 
116
+ def timeout?(id, time)
117
+ return false unless (Time.now - time) > @timeout
118
+ log.debug "Event #{id} finished by timeout #{time}"
119
+ true
120
+ end
121
+
119
122
  # Request Power On for droplet
120
123
  #
121
124
  def power_on(id)
@@ -123,9 +126,9 @@ module DoSnapshot
123
126
  event = ::DigitaloceanC::Droplet.power_on(id)
124
127
  case event && event.status
125
128
  when 'OK'
126
- Log.info 'Power On has been requested.'
129
+ log.info 'Power On has been requested.'
127
130
  else
128
- Log.error 'Power On failed to request.'
131
+ log.error 'Power On failed to request.'
129
132
  end
130
133
  end
131
134
  end
@@ -42,7 +42,7 @@ module DoSnapshot
42
42
  instance = droplet(id)
43
43
 
44
44
  if instance.status && instance.status.include?('active')
45
- Log.error 'Droplet is still running.'
45
+ log.error 'Droplet is still running.'
46
46
  else
47
47
  power_on id
48
48
  end
@@ -74,14 +74,14 @@ module DoSnapshot
74
74
 
75
75
  # Cleanup our snapshots.
76
76
  #
77
- def cleanup_snapshots(instance, size) # rubocop:disable MethodLength
77
+ def cleanup_snapshots(instance, size)
78
78
  (0..size).each do |i|
79
79
  # noinspection RubyResolve
80
80
  snapshot = instance.snapshot_ids[i]
81
81
  event = client.images.delete(id: snapshot)
82
82
 
83
83
  unless event.is_a?(TrueClass)
84
- Log.debug event
84
+ log.debug event
85
85
  event = false
86
86
  end
87
87
 
@@ -90,16 +90,16 @@ module DoSnapshot
90
90
  end
91
91
 
92
92
  def check_keys
93
- Log.debug 'Checking DigitalOcean Access Token.'
93
+ log.debug 'Checking DigitalOcean Access Token.'
94
94
  %w( DIGITAL_OCEAN_ACCESS_TOKEN ).each do |key|
95
- Log.error "You must have #{key} in environment or set it via options." if ENV[key].blank?
95
+ log.error "You must have #{key} in environment or set it via options." if ENV[key].blank?
96
96
  end
97
97
  end
98
98
 
99
99
  # Set id's of Digital Ocean API.
100
100
  #
101
101
  def set_id
102
- Log.debug 'Setting DigitalOcean Access Token.'
102
+ log.debug 'Setting DigitalOcean Access Token.'
103
103
  @client = ::DropletKit::Client.new(access_token: ENV['DIGITAL_OCEAN_ACCESS_TOKEN'])
104
104
  end
105
105
 
@@ -107,9 +107,9 @@ module DoSnapshot
107
107
 
108
108
  def after_cleanup(droplet_id, droplet_name, snapshot, event)
109
109
  if !event
110
- Log.error "Destroy of snapshot #{snapshot} for droplet id: #{droplet_id} name: #{droplet_name} is failed."
110
+ log.error "Destroy of snapshot #{snapshot} for droplet id: #{droplet_id} name: #{droplet_name} is failed."
111
111
  else
112
- Log.debug "Snapshot: #{snapshot} delete requested."
112
+ log.debug "Snapshot: #{snapshot} delete requested."
113
113
  end
114
114
  end
115
115
 
@@ -118,7 +118,7 @@ module DoSnapshot
118
118
  #
119
119
  def get_event_status(id, time)
120
120
  if (Time.now - time) > @timeout
121
- Log.debug "Event #{id} finished by timeout #{time}"
121
+ log.debug "Event #{id} finished by timeout #{time}"
122
122
  return true
123
123
  end
124
124
 
@@ -135,9 +135,9 @@ module DoSnapshot
135
135
  # noinspection RubyResolve
136
136
  event = client.droplet_actions.power_on(droplet_id: id)
137
137
  if event.status.include?('in-progress')
138
- Log.info 'Power On has been requested.'
138
+ log.info 'Power On has been requested.'
139
139
  else
140
- Log.error 'Power On failed to request.'
140
+ log.error 'Power On failed to request.'
141
141
  end
142
142
  end
143
143
  end
@@ -1,14 +1,17 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  require 'thor'
3
3
  require 'do_snapshot'
4
- require_relative 'command'
5
- require_relative 'mail'
6
4
  require_relative 'log'
5
+ require_relative 'mail'
6
+ require_relative 'command'
7
7
 
8
8
  module DoSnapshot
9
9
  # CLI is here
10
10
  #
11
11
  class CLI < Thor # rubocop:disable ClassLength
12
+ include DoSnapshot::Log
13
+ include DoSnapshot::Mail
14
+
12
15
  default_task :snap
13
16
 
14
17
  map %w( c s create ) => :snap
@@ -154,11 +157,10 @@ module DoSnapshot
154
157
  desc: 'DIGITAL_OCEAN_API_KEY. if you can\'t use environment.'
155
158
 
156
159
  def snap
157
- Command.load_options options, %w( log mail smtp trace digital_ocean_client_id digital_ocean_api_key digital_ocean_access_token )
158
- Command.snap
160
+ command.snap
159
161
  rescue => e
160
- Command.fail_power_off(e) if [SnapshotCreateError, DropletShutdownError].include?(e.class)
161
- Log.error e.message
162
+ command.fail_power_off(e) if [SnapshotCreateError, DropletShutdownError].include?(e.class)
163
+ log.error e.message
162
164
  backtrace(e) if options.include? 'trace'
163
165
  send_error
164
166
  end
@@ -169,22 +171,30 @@ module DoSnapshot
169
171
  end
170
172
 
171
173
  no_commands do
174
+ def command
175
+ @command ||= Command.new(options,
176
+ %w( log smtp mail trace digital_ocean_client_id digital_ocean_api_key digital_ocean_access_token ))
177
+ end
178
+
179
+ def update_command
180
+ command.load_options(options,
181
+ %w( log smtp mail trace digital_ocean_client_id digital_ocean_api_key digital_ocean_access_token ))
182
+ end
183
+
172
184
  def set_mailer
173
- Mail.opts = options['mail']
174
- Mail.smtp = options['smtp']
185
+ Mail.load_options(opts: options['mail'], smtp: options['smtp'])
175
186
  end
176
187
 
177
188
  def send_error
178
- return unless Mail.opts
189
+ return unless mailer.opts
179
190
 
180
191
  Mail.opts[:subject] = 'Digital Ocean: Error.'
181
192
  Mail.opts[:body] = 'Please check your droplets.'
182
- Mail.notify
193
+ mailer.notify
183
194
  end
184
195
 
185
196
  def set_logger
186
- Log.quiet = options['quiet']
187
- Log.verbose = options['trace']
197
+ Log.load_options(quiet: options['quiet'], verbose: options['trace'])
188
198
  # Use Thor shell
189
199
  Log.shell = shell unless options['quiet']
190
200
  init_logger if options.include?('log')
@@ -197,7 +207,7 @@ module DoSnapshot
197
207
 
198
208
  def backtrace(e)
199
209
  e.backtrace.each do |t|
200
- Log.error t
210
+ log.error t
201
211
  end
202
212
  end
203
213
  end
@@ -5,167 +5,179 @@ module DoSnapshot
5
5
  # Our commands live here :)
6
6
  #
7
7
  class Command # rubocop:disable ClassLength
8
- class << self
9
- def snap
10
- Log.info 'Start performing operations'
11
- work_with_droplets
12
- Log.info 'All operations has been finished.'
8
+ include DoSnapshot::Log
9
+ include DoSnapshot::Mail
13
10
 
14
- Mail.notify if notify && !quiet
15
- end
11
+ def initialize(*args)
12
+ load_options(*args)
13
+ end
16
14
 
17
- def load_options(options = {}, skip = %w())
18
- options.each_pair do |key, option|
19
- send("#{key}=", option) unless skip.include?(key)
20
- end if options
21
- end
15
+ def snap
16
+ log.info 'Start performing operations'
17
+ work_with_droplets
18
+ log.info 'All operations has been finished.'
22
19
 
23
- def fail_power_off(e)
24
- return unless e && e.id
25
- api.start_droplet(e.id)
26
- rescue
27
- raise DropletFindError, e.message, e.backtrace
28
- end
20
+ mailer.notify if notify && !quiet
21
+ end
22
+
23
+ def fail_power_off(e)
24
+ return unless e && e.id
25
+ api.start_droplet(e.id)
26
+ rescue
27
+ raise DropletFindError, e.message, e.backtrace
28
+ end
29
+
30
+ def load_options(options = {}, skip = %w())
31
+ reset_options
32
+ options.each_pair do |key, option|
33
+ send("#{key}=", option) unless skip.include?(key)
34
+ end if options
35
+ end
29
36
 
30
- def stop_droplet(droplet)
31
- Log.debug 'Shutting down droplet.'
32
- api.stop_droplet(droplet.id) unless droplet.status.include? 'off'
37
+ def reset_options
38
+ %i(droplets exclude only keep quiet stop clean timeout delay protocol threads api).each do |key|
39
+ send("#{key}=", nil)
33
40
  end
41
+ end
34
42
 
35
- # Trying to create a snapshot.
36
- #
37
- def create_snapshot(droplet) # rubocop:disable MethodLength,Metrics/AbcSize
38
- Log.info "Start creating snapshot for droplet id: #{droplet.id} name: #{droplet.name}."
43
+ def stop_droplet(droplet)
44
+ log.debug 'Shutting down droplet.'
45
+ api.stop_droplet(droplet.id) unless droplet.status.include? 'off'
46
+ end
39
47
 
40
- today = DateTime.now
41
- name = "#{droplet.name}_#{today.strftime('%Y_%m_%d')}"
42
- # noinspection RubyResolve
43
- snapshot_size = api.snapshots(droplet).size
48
+ # Trying to create a snapshot.
49
+ #
50
+ def create_snapshot(droplet) # rubocop:disable MethodLength,Metrics/AbcSize
51
+ log.info "Start creating snapshot for droplet id: #{droplet.id} name: #{droplet.name}."
44
52
 
45
- Log.debug 'Wait until snapshot will be created.'
53
+ today = DateTime.now
54
+ name = "#{droplet.name}_#{today.strftime('%Y_%m_%d')}"
55
+ # noinspection RubyResolve
56
+ snapshot_size = api.snapshots(droplet).size
46
57
 
47
- api.create_snapshot droplet.id, name
58
+ log.debug 'Wait until snapshot will be created.'
48
59
 
49
- snapshot_size += 1
60
+ api.create_snapshot droplet.id, name
50
61
 
51
- Log.info "Snapshot name: #{name} created successfully."
52
- Log.info "Droplet id: #{droplet.id} name: #{droplet.name} snapshots: #{snapshot_size}."
62
+ snapshot_size += 1
53
63
 
54
- # Cleanup snapshots.
55
- cleanup_snapshots droplet, snapshot_size if clean
56
- rescue => e
57
- case e.class.to_s
58
- when 'DoSnapshot::SnapshotCleanupError'
59
- raise e.class, e.message, e.backtrace
60
- else
61
- raise SnapshotCreateError.new(droplet.id), e.message, e.backtrace
62
- end
63
- end
64
+ log.info "Snapshot name: #{name} created successfully."
65
+ log.info "Droplet id: #{droplet.id} name: #{droplet.name} snapshots: #{snapshot_size}."
64
66
 
65
- def api
66
- @api ||= DoSnapshot::Adapter.api(protocol, delay: delay, timeout: timeout)
67
+ # Cleanup snapshots.
68
+ cleanup_snapshots droplet, snapshot_size if clean
69
+ rescue => e
70
+ case e.class.to_s
71
+ when 'DoSnapshot::SnapshotCleanupError'
72
+ raise e.class, e.message, e.backtrace
73
+ else
74
+ raise SnapshotCreateError.new(droplet.id), e.message, e.backtrace
67
75
  end
76
+ end
68
77
 
69
- protected
78
+ def api
79
+ @api ||= DoSnapshot::Adapter.api(protocol, delay: delay, timeout: timeout)
80
+ end
70
81
 
71
- attr_accessor :droplets, :exclude, :only
72
- attr_accessor :keep, :quiet, :stop, :clean, :timeout, :delay, :protocol
82
+ protected
73
83
 
74
- attr_writer :notify, :threads, :api
84
+ attr_accessor :droplets, :exclude, :only
85
+ attr_accessor :keep, :quiet, :stop, :clean, :timeout, :delay, :protocol
75
86
 
76
- def notify
77
- @notify ||= false
78
- end
87
+ attr_writer :threads, :api
79
88
 
80
- def threads
81
- @threads ||= []
82
- end
89
+ def notify
90
+ @notify ||= false
91
+ end
83
92
 
84
- # Working with list of droplets.
85
- #
86
- def work_with_droplets
87
- load_droplets
88
- dispatch_droplets
89
- Log.debug 'Working with list of DigitalOcean droplets'
90
- thread_chain
91
- end
93
+ def threads
94
+ @threads ||= []
95
+ end
92
96
 
93
- # Getting droplets list from API.
94
- # And store into object.
95
- #
96
- def load_droplets
97
- Log.debug 'Loading list of DigitalOcean droplets'
98
- self.droplets = api.droplets
99
- end
97
+ # Working with list of droplets.
98
+ #
99
+ def work_with_droplets
100
+ load_droplets
101
+ dispatch_droplets
102
+ log.debug 'Working with list of DigitalOcean droplets'
103
+ thread_chain
104
+ end
100
105
 
101
- # Dispatch received droplets, each by each.
102
- #
103
- def dispatch_droplets
104
- droplets.each do |droplet|
105
- id = droplet.id.to_s
106
- next if exclude.include? id
107
- next unless only.empty? || only.include?(id)
106
+ # Getting droplets list from API.
107
+ # And store into object.
108
+ #
109
+ def load_droplets
110
+ log.debug 'Loading list of DigitalOcean droplets'
111
+ self.droplets = api.droplets
112
+ end
108
113
 
109
- prepare_droplet id, droplet.name
110
- end
111
- end
114
+ # Dispatch received droplets, each by each.
115
+ #
116
+ def dispatch_droplets
117
+ droplets.each do |droplet|
118
+ id = droplet.id.to_s
119
+ next if exclude.include? id
120
+ next unless only.empty? || only.include?(id)
112
121
 
113
- # Join threads
114
- #
115
- def thread_chain
116
- threads.each(&:join)
122
+ prepare_droplet id, droplet.name
117
123
  end
124
+ end
118
125
 
119
- # Run threads
120
- #
121
- def thread_runner(droplet)
122
- threads << Thread.new do
123
- stop_droplet droplet
124
- create_snapshot droplet
125
- end
126
- end
126
+ # Join threads
127
+ #
128
+ def thread_chain
129
+ threads.each(&:join)
130
+ end
127
131
 
128
- # Preparing droplet to take a snapshot.
129
- # Droplet instance must be powered off first!
130
- #
131
- def prepare_droplet(id, name)
132
- Log.debug "Droplet id: #{id} name: #{name} "
133
- droplet = api.droplet id
134
-
135
- return unless droplet
136
- Log.info "Preparing droplet id: #{droplet.id} name: #{droplet.name} to take snapshot."
137
- return if too_much_snapshots(droplet)
138
- thread_runner(droplet)
132
+ # Run threads
133
+ #
134
+ def thread_runner(droplet)
135
+ threads << Thread.new do
136
+ stop_droplet droplet
137
+ create_snapshot droplet
139
138
  end
139
+ end
140
140
 
141
- def too_much_snapshots(instance)
142
- # noinspection RubyResolve
143
- return false unless api.snapshots(instance).size >= keep
144
- warning_size(instance.id, instance.name, keep)
145
- stop ? true : false
146
- end
141
+ # Preparing droplet to take a snapshot.
142
+ # Droplet instance must be powered off first!
143
+ #
144
+ def prepare_droplet(id, name)
145
+ log.debug "Droplet id: #{id} name: #{name} "
146
+ droplet = api.droplet id
147
+
148
+ return unless droplet
149
+ log.info "Preparing droplet id: #{droplet.id} name: #{droplet.name} to take snapshot."
150
+ return if too_much_snapshots(droplet)
151
+ thread_runner(droplet)
152
+ end
153
+
154
+ def too_much_snapshots(instance)
155
+ # noinspection RubyResolve
156
+ return false unless api.snapshots(instance).size >= keep
157
+ warning_size(instance.id, instance.name, keep)
158
+ stop ? true : false
159
+ end
147
160
 
148
- # Cleanup our snapshots.
149
- #
150
- def cleanup_snapshots(droplet, size) # rubocop:disable Metrics/AbcSize
151
- return unless size > keep
161
+ # Cleanup our snapshots.
162
+ #
163
+ def cleanup_snapshots(droplet, size) # rubocop:disable Metrics/AbcSize
164
+ return unless size > keep
152
165
 
153
- warning_size(droplet.id, droplet.name, size)
166
+ warning_size(droplet.id, droplet.name, size)
154
167
 
155
- Log.debug "Cleaning up snapshots for droplet id: #{droplet.id} name: #{droplet.name}."
168
+ log.debug "Cleaning up snapshots for droplet id: #{droplet.id} name: #{droplet.name}."
156
169
 
157
- api.cleanup_snapshots(droplet, size - keep - 1)
158
- rescue => e
159
- raise SnapshotCleanupError, e.message, e.backtrace
160
- end
170
+ api.cleanup_snapshots(droplet, size - keep - 1)
171
+ rescue => e
172
+ raise SnapshotCleanupError, e.message, e.backtrace
173
+ end
161
174
 
162
- # Helpers
163
- #
164
- def warning_size(id, name, keep)
165
- message = "For droplet with id: #{id} and name: #{name} the maximum number #{keep} of snapshots is reached."
166
- Log.warning message
167
- self.notify = true
168
- end
175
+ # Helpers
176
+ #
177
+ def warning_size(id, name, keep)
178
+ message = "For droplet with id: #{id} and name: #{name} the maximum number #{keep} of snapshots is reached."
179
+ log.warn message
180
+ @notify = true
169
181
  end
170
182
  end
171
183
  end
@@ -4,33 +4,32 @@ require 'logger'
4
4
  module DoSnapshot
5
5
  # Shared logger
6
6
  #
7
- class Log
8
- class << self
9
- attr_accessor :logger, :shell, :quiet, :verbose
10
- attr_writer :buffer
11
-
12
- def buffer
13
- @buffer ||= %w()
14
- end
7
+ module Log
8
+ def log
9
+ UniversalLogger
10
+ end
15
11
 
16
- def info(message)
17
- log :info, message
12
+ # UniversalLogger is module to deal with singleton methods.
13
+ # Used to give classes access only for selected methods
14
+ #
15
+ module UniversalLogger
16
+ %i(info warn error debug).each do |type|
17
+ define_singleton_method(type) { |message| Log.log type, message }
18
18
  end
19
+ end
19
20
 
20
- def warning(message)
21
- log :warn, message
22
- end
21
+ class << self
22
+ attr_accessor :logger, :shell, :quiet, :verbose
23
+ attr_writer :buffer
23
24
 
24
- def error(message)
25
- log :error, message
25
+ def load_options(options = {})
26
+ options.each { |key, option| send("#{key}=", option) }
26
27
  end
27
28
 
28
- def debug(message)
29
- log :debug, message
29
+ def buffer
30
+ @buffer ||= %w()
30
31
  end
31
32
 
32
- protected
33
-
34
33
  def log(type, message)
35
34
  buffer << message
36
35
  logger.send(type, message) if logger
@@ -38,6 +37,8 @@ module DoSnapshot
38
37
  say message, color(type) unless print?(type)
39
38
  end
40
39
 
40
+ protected
41
+
41
42
  def print?(type)
42
43
  (type == :debug && !verbose) || quiet
43
44
  end
@@ -2,17 +2,63 @@
2
2
  require 'date'
3
3
  require 'pony'
4
4
  require_relative 'core_ext/hash'
5
+ require_relative 'log'
5
6
 
6
7
  module DoSnapshot
7
8
  # Shared mailer.
8
9
  #
9
- class Mail
10
+ module Mail
11
+ def mailer
12
+ UniversalMailer
13
+ end
14
+
15
+ # UniversalMailer is module to deal with singleton methods.
16
+ # Used to give classes access only for selected methods
17
+ #
18
+ module UniversalMailer
19
+ module_function
20
+
21
+ def notify
22
+ Mail.notify
23
+ end
24
+ end
25
+
10
26
  class << self
11
- attr_accessor :opts
12
- attr_writer :smtp, :opts_default, :smtp_default
27
+ include DoSnapshot::Log
28
+
29
+ attr_writer :mailer, :opts_default, :smtp_default
30
+
31
+ def load_options(options = {})
32
+ options.each { |key, option| send("#{key}=", option) }
33
+ end
34
+
35
+ def reset_options
36
+ @opts = opts_default
37
+ @smtp = smtp_default
38
+ end
39
+
40
+ def mailer
41
+ @mailer ||= Pony.method(:mail)
42
+ end
13
43
 
14
44
  def smtp
15
- @smtp ||= {}
45
+ @smtp ||= smtp_default.dup
46
+ end
47
+
48
+ def opts
49
+ @opts ||= opts_default.dup
50
+ end
51
+
52
+ def smtp=(options)
53
+ options.each_pair do |key, value|
54
+ smtp[key.to_sym] = value
55
+ end if options
56
+ end
57
+
58
+ def opts=(options)
59
+ options.each_pair do |key, value|
60
+ opts[key.to_sym] = value
61
+ end if options
16
62
  end
17
63
 
18
64
  # Sending message via Hash params.
@@ -20,17 +66,10 @@ module DoSnapshot
20
66
  # Options:: --mail to:mail@somehost.com from:from@host.com --smtp address:smtp.gmail.com user_name:someuser password:somepassword
21
67
  #
22
68
  def notify
23
- return unless opts
24
-
25
- opts.symbolize_keys!
26
- smtp.symbolize_keys!
27
-
28
- opts_setup
29
- smtp_setup
30
-
31
- Log.debug 'Sending e-mail notification.'
69
+ setup_notify
70
+ log.debug 'Sending e-mail notification.'
32
71
  # Look into your inbox :)
33
- Pony.mail(opts)
72
+ mailer.call(opts)
34
73
  end
35
74
 
36
75
  protected
@@ -52,17 +91,8 @@ module DoSnapshot
52
91
  }
53
92
  end
54
93
 
55
- def opts_setup
56
- opts_default.each_pair do |key, value|
57
- opts[key] = value unless opts.include? key
58
- end
59
- opts[:body] = "#{opts[:body]}\n\nTrace: #{DateTime.now}\n#{Log.buffer.join("\n")}"
60
- end
61
-
62
- def smtp_setup
63
- smtp_default.each_pair do |key, value|
64
- smtp[key] = value unless smtp.include? key
65
- end
94
+ def setup_notify
95
+ opts[:body] = "#{opts[:body]}\n\nTrace: #{DateTime.now}\n#{Log.buffer.join("\n")}"
66
96
  opts[:via_options] = smtp
67
97
  end
68
98
  end
@@ -2,5 +2,5 @@
2
2
  # Current version
3
3
  #
4
4
  module DoSnapshot
5
- VERSION = '0.0.15'
5
+ VERSION = '0.2.2'
6
6
  end
data/lib/do_snapshot.rb CHANGED
@@ -22,7 +22,7 @@ module DoSnapshot
22
22
  #
23
23
  class DropletShutdownError < RequestActionError
24
24
  def initialize(*args)
25
- Log.error "Droplet id: #{args[0]} is Failed to Power Off."
25
+ Log.log :error, "Droplet id: #{args[0]} is Failed to Power Off."
26
26
  super
27
27
  end
28
28
  end
@@ -32,7 +32,7 @@ module DoSnapshot
32
32
  #
33
33
  class SnapshotCreateError < RequestActionError
34
34
  def initialize(*args)
35
- Log.error "Droplet id: #{args[0]} is Failed to Snapshot."
35
+ Log.log :error, "Droplet id: #{args[0]} is Failed to Snapshot."
36
36
  super
37
37
  end
38
38
  end
@@ -42,7 +42,7 @@ module DoSnapshot
42
42
  #
43
43
  class DropletFindError < RequestError
44
44
  def initialize(*args)
45
- Log.error 'Droplet Not Found'
45
+ Log.log :error, 'Droplet Not Found'
46
46
  super
47
47
  end
48
48
  end
@@ -52,7 +52,7 @@ module DoSnapshot
52
52
  #
53
53
  class DropletListError < RequestError
54
54
  def initialize(*args)
55
- Log.error 'Droplet Listing is failed to retrieve'
55
+ Log.log :error, 'Droplet Listing is failed to retrieve'
56
56
  super
57
57
  end
58
58
  end
@@ -6,7 +6,6 @@ describe DoSnapshot::CLI do
6
6
  include_context 'api_v1_helpers'
7
7
 
8
8
  subject(:cli) { described_class }
9
- subject(:command) { DoSnapshot::Command }
10
9
  subject(:api) { DoSnapshot::Adapter::Digitalocean }
11
10
 
12
11
  describe '.initialize' do
@@ -28,7 +27,7 @@ describe DoSnapshot::CLI do
28
27
  stub_all_api(%w(100825 100823))
29
28
  hash_attribute_eq_no_stub(exclude: excluded_droplets, only: %w())
30
29
 
31
- expect(command.send('exclude'))
30
+ expect(@cli.command.send('exclude'))
32
31
  .to eq excluded_droplets
33
32
  end
34
33
 
@@ -37,7 +36,7 @@ describe DoSnapshot::CLI do
37
36
  stub_all_api(selected_droplets)
38
37
  hash_attribute_eq_no_stub(only: selected_droplets)
39
38
 
40
- expect(command.send('only'))
39
+ expect(@cli.command.send('only'))
41
40
  .to eq selected_droplets
42
41
  end
43
42
 
@@ -93,19 +92,19 @@ describe DoSnapshot::CLI do
93
92
  end
94
93
 
95
94
  it 'with mail' do
96
- hash_attribute_eq(mail_options)
95
+ hash_attribute_eq(mail: mail_options)
97
96
  end
98
97
 
99
98
  it 'with no mail' do
100
- without_hash_attribute_eq(mail_options)
99
+ without_hash_attribute_eq(mail: mail_options)
101
100
  end
102
101
 
103
102
  it 'with smtp' do
104
- hash_attribute_eq(smtp_options)
103
+ hash_attribute_eq(smtp: smtp_options)
105
104
  end
106
105
 
107
106
  it 'with no smtp' do
108
- without_hash_attribute_eq(smtp_options)
107
+ without_hash_attribute_eq(smtp: smtp_options)
109
108
  end
110
109
 
111
110
  it 'with log' do
@@ -153,9 +152,9 @@ describe DoSnapshot::CLI do
153
152
  stub_all_api
154
153
  options = default_options.merge!(:"#{name}" => value)
155
154
  @cli.options = @cli.options.merge(options)
156
- @cli.snap
155
+ @cli.update_command
157
156
 
158
- expect(command.send(name))
157
+ expect(@cli.command.send(name))
159
158
  .to eq value
160
159
  end
161
160
 
@@ -163,7 +162,7 @@ describe DoSnapshot::CLI do
163
162
  stub_all_api
164
163
  options = default_options.merge!(hash)
165
164
  @cli.options = @cli.options.merge(options)
166
- @cli.snap
165
+ @cli.update_command
167
166
  end
168
167
 
169
168
  def with_hash_attribute_eq(hash)
@@ -181,11 +180,11 @@ describe DoSnapshot::CLI do
181
180
  def hash_attribute_eq_no_stub(hash)
182
181
  options = default_options.merge!(hash)
183
182
  @cli.options = @cli.options.merge(options)
184
- @cli.snap
183
+ @cli.update_command
185
184
  end
186
185
 
187
186
  def set_api_attribute(options = { delay: delay, timeout: timeout }) # rubocop:disable Style/AccessorMethodName
188
- command.send('api=', api.new(options))
187
+ @cli.command.send('api=', api.new(options))
189
188
  end
190
189
 
191
190
  before(:each) do
@@ -6,7 +6,7 @@ describe DoSnapshot::Command do
6
6
  include_context 'uri_helpers'
7
7
  include_context 'api_v1_helpers'
8
8
 
9
- subject(:cmd) { DoSnapshot::Command }
9
+ subject(:cmd) { DoSnapshot::Command.new }
10
10
  subject(:log) { DoSnapshot::Log }
11
11
 
12
12
  describe '.snap' do
@@ -144,7 +144,6 @@ describe DoSnapshot::Command do
144
144
 
145
145
  def load_options(options = nil)
146
146
  options ||= default_options
147
- cmd.send('api=', nil)
148
147
  cmd.load_options(options, [:log, :mail, :smtp, :trace, :digital_ocean_client_id, :digital_ocean_api_key])
149
148
  end
150
149
 
@@ -0,0 +1,15 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe DoSnapshot::Mail do
5
+ include_context 'spec'
6
+
7
+ describe 'will send mail with options' do
8
+ it '#notify' do
9
+ DoSnapshot::Mail.reset_options
10
+ DoSnapshot::Mail.load_options(opts: mail_options, smtp: smtp_options)
11
+ expect { DoSnapshot::Mail.notify }.not_to raise_error
12
+ expect(DoSnapshot::Mail.smtp[:address]).to eq(smtp_options[:address])
13
+ end
14
+ end
15
+ end
@@ -4,6 +4,10 @@ require 'spec_helper'
4
4
  shared_context 'spec' do
5
5
  include_context 'api_helpers'
6
6
 
7
+ def do_not_send_email
8
+ allow(Pony).to receive(:deliver)
9
+ end
10
+
7
11
  let(:client_key) { 'foo' }
8
12
  let(:api_key) { 'bar' }
9
13
  let(:access_token) { 'sometoken' }
@@ -11,7 +15,7 @@ shared_context 'spec' do
11
15
  let(:droplet_id) { '100823' }
12
16
  let(:image_id) { '5019770' }
13
17
  let(:image_id2) { '5019903' }
14
- let(:cli_keys) { Thor::CoreExt::HashWithIndifferentAccess.new(digital_ocean_client_id: 'NOTFOO', digital_ocean_client_key: 'NOTBAR', digital_ocean_access_token: 'NOTTOK') }
18
+ let(:cli_keys) { Thor::CoreExt::HashWithIndifferentAccess.new(digital_ocean_client_id: 'NOTFOO', digital_ocean_api_key: 'NOTBAR', digital_ocean_access_token: 'NOTTOK') }
15
19
  let(:snapshot_name) { "foo_#{DateTime.now.strftime('%Y_%m_%d')}" }
16
20
  let(:default_options) { Hash[protocol: 1, only: %w( 100823 ), exclude: %w(), keep: 3, stop: false, trace: true, clean: true, delay: 0, timeout: 600, droplets: nil, threads: []] }
17
21
  let(:no_exclude) { [] }
@@ -30,7 +34,7 @@ shared_context 'spec' do
30
34
  let(:smtp_options) { Thor::CoreExt::HashWithIndifferentAccess.new(address: 'smtp.gmail.com', port: '25', user_name: 'someuser', password: 'somepassword') }
31
35
  let(:log) { Thor::CoreExt::HashWithIndifferentAccess.new(log: "#{project_path}/log/test.log") }
32
36
 
33
- def stub_all_api(droplets = nil, active = false) # rubocop:disable MethodLength
37
+ def stub_all_api(droplets = nil, active = false)
34
38
  drops = []
35
39
  droplets ||= [droplet_id]
36
40
  droplets.each do |droplet|
@@ -90,6 +94,7 @@ shared_context 'spec' do
90
94
  end
91
95
 
92
96
  before(:each) do
97
+ do_not_send_email
93
98
  set_api_keys
94
99
  end
95
100
  end
data/spec/spec_helper.rb CHANGED
@@ -2,7 +2,6 @@
2
2
  require 'coveralls'
3
3
  Coveralls.wear! do
4
4
  add_filter '/spec/*'
5
- add_filter '/lib/do_snapshot/mail.rb'
6
5
  end
7
6
 
8
7
  require 'do_snapshot/cli'
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: do_snapshot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.15
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Merkulov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-06 00:00:00.000000000 Z
11
+ date: 2015-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 4.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 4.0.0
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: digitalocean_c
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -95,6 +109,7 @@ files:
95
109
  - spec/do_snapshot/adapter/digitalocean_v2_spec.rb
96
110
  - spec/do_snapshot/cli_spec.rb
97
111
  - spec/do_snapshot/command_spec.rb
112
+ - spec/do_snapshot/mail_spec.rb
98
113
  - spec/do_snapshots_spec.rb
99
114
  - spec/fixtures/digitalocean/v1/error_message.json
100
115
  - spec/fixtures/digitalocean/v1/response_event.json
@@ -155,6 +170,7 @@ test_files:
155
170
  - spec/do_snapshot/adapter/digitalocean_v2_spec.rb
156
171
  - spec/do_snapshot/cli_spec.rb
157
172
  - spec/do_snapshot/command_spec.rb
173
+ - spec/do_snapshot/mail_spec.rb
158
174
  - spec/do_snapshots_spec.rb
159
175
  - spec/fixtures/digitalocean/v1/error_message.json
160
176
  - spec/fixtures/digitalocean/v1/response_event.json