do_snapshot 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d4b1d0886088780b79e06c589eba381d8152ac73
4
- data.tar.gz: d5bd6e4651f3265200457d0ffb107d8093325b71
3
+ metadata.gz: 5ee1fb26e08febbd07bd95db15ede7e27288c6ac
4
+ data.tar.gz: e94d18d396f7afe4a2746b7d5f26ab4bf162cc1e
5
5
  SHA512:
6
- metadata.gz: 36e0890a6ea0f126053fad03b94211b9f8d7453c2318be21a32f241dd18d2dbfede194c279d1f19c20c9c59f566c888356579c8c4d4e9f55798e62da62e90cdd
7
- data.tar.gz: 09884729d366d5effb5b2ce263e82bb113a0afb4c1c21aead12502beea9d38728a5f612a55487b0b7efd3657f8fc3c43a607b15ce4ed7277bdcce2117eba8a9e
6
+ metadata.gz: d9222fbba54f8d23156befea3fbe36aebb173e566f29710d09a84c9ab4915ad177e8800818744c54c02ece99fd167b30a013054ff526fc749ce128358cd66e6c
7
+ data.tar.gz: bc3c05e81971b6a62e217785035361179e2832c9b52f8cab5371d64655eedf57dded6bbc9f5064aa340fbfa1584adc0028c00307f6ff951ffcfdba732fe991c0
data/README.md CHANGED
@@ -13,6 +13,10 @@
13
13
  Use this tool to backup DigitalOcean droplet's via snapshot method, on the fly!
14
14
 
15
15
  ## API Changes:
16
+ - 03.08.16: DO now automagically keeps our droplets running when snapshot is processing, so:
17
+ Added options `--shutdown`, `--no-shutdown`.
18
+ `shutdown` now disabled by default, no downtime anymore, `YES`!
19
+ If you want `shutdown` back use `--shutdown` option.
16
20
  - 08.01.16: now we have to use DO API V2 only, because V1 is not work anymore.
17
21
  - 17.10.15: now we use DO API V2 by default, due V1 deprecation at 11.2015.
18
22
 
@@ -87,8 +91,9 @@ If you want to set keys without environment, than set it via options when you ru
87
91
  ### How-To
88
92
 
89
93
  ##### Tutorials:
90
- - [Longren Tutorial](https://longren.io/automate-making-snapshots-of-your-digitalocean-droplets/)
91
- - [Arun Kumar Tutorial](http://www.ashout.com/automate-digital-ocean-droplet-snaphot/)
94
+ - [Automate Taking Snapshots of Your DigitalOcean Droplets with DOSnapshot
95
+ , Tyler Longren](https://longren.io/automate-making-snapshots-of-your-digitalocean-droplets/)
96
+ - [How to Automate Taking Digital Ocean Droplet Snaphot with DoSnapShot Script, Arun Kumar](http://www.ashout.com/automate-digital-ocean-droplet-snaphot/)
92
97
 
93
98
  Here we `keeping` only 5 **latest** snapshots and cleanup older after new one is created. If creation of snapshots failed no one will be deleted. By default we keeping `10` droplets.
94
99
 
@@ -147,6 +152,7 @@ For working mailer you need to set e-mail settings via run options.
147
152
  Options:
148
153
  -p, [--protocol=1] # Select api version.
149
154
  # Default: 2
155
+ [--shutdown], [--no-shutdown] # Check if you want to stop your droplet before the snapshot.
150
156
  -o, [--only=123456 123456 123456] # Select some droplets.
151
157
  -e, [--exclude=123456 123456 123456] # Except some droplets.
152
158
  -k, [--keep=5] # How much snapshots you want to keep?
@@ -160,7 +166,7 @@ For working mailer you need to set e-mail settings via run options.
160
166
  -l, [--log=/Users/someone/.do_snapshot/main.log] # Log file path. By default logging is disabled.
161
167
  -c, [--clean], [--no-clean] # Cleanup snapshots after create. If you have more images than you want to `keep`, older will be deleted.
162
168
  -s, [--stop], [--no-stop] # Stop creating snapshots if maximum is reached.
163
- [--stop-by-power], [--no-stop-by-power] # Check if droplet stopped by its power status instead of waiting for event completed state.
169
+ [--stop-by-power], [--no-stop-by-power] # Droplet stop method, by it's power status (instead of waiting for event completed state).
164
170
  -v, [--trace], [--no-trace] # Verbose mode.
165
171
  -q, [--quiet], [--no-quiet] # Quiet mode. If don't need any messages in console.
166
172
  [--digital-ocean-access-token=YOURLONGAPITOKEN] # DIGITAL_OCEAN_ACCESS_TOKEN. if you can't use environment.
@@ -189,7 +195,6 @@ Support this project and others by [merqlove](https://gratipay.com/~merqlove/) v
189
195
  ## Dependencies:
190
196
 
191
197
  - [Thor](https://github.com/erikhuda/thor) for CLI.
192
- - [Digitalocean](https://github.com/scottmotte/digitalocean) for API V1 requests.
193
198
  - [Barge](https://github.com/blom/barge) for API V2 requests.
194
199
  - [Pony](https://github.com/benprew/pony) for mail notifications.
195
200
 
@@ -95,7 +95,7 @@ module DoSnapshot
95
95
  def check_keys
96
96
  logger.debug 'Checking DigitalOcean Access Token.'
97
97
  %w( DIGITAL_OCEAN_ACCESS_TOKEN ).each do |key|
98
- fail DoSnapshot::NoTokenError, "You must have #{key} in environment or set it via options." if ENV[key].blank?
98
+ fail DoSnapshot::NoTokenError, "You must have #{key} in environment or set it via options." if ENV[key].nil? || ENV[key].empty?
99
99
  end
100
100
  end
101
101
 
@@ -82,6 +82,10 @@ module DoSnapshot
82
82
  aliases: %w( -p ),
83
83
  banner: '1',
84
84
  desc: 'Select api version.'
85
+ method_option :shutdown,
86
+ default: false,
87
+ type: :boolean,
88
+ desc: 'Check if you want to stop droplet before the snapshot.'
85
89
  method_option :only,
86
90
  type: :array,
87
91
  default: [],
@@ -137,7 +141,7 @@ module DoSnapshot
137
141
  desc: 'Stop creating snapshots if maximum is reached.'
138
142
  method_option :stop_by_power,
139
143
  type: :boolean,
140
- desc: 'Check if droplet stopped by its power status instead of waiting for event completed state.'
144
+ desc: "Droplet stop method, by it's power status (instead of waiting for event completed state)."
141
145
  method_option :trace,
142
146
  type: :boolean,
143
147
  aliases: %w( -v ),
@@ -7,6 +7,10 @@ module DoSnapshot
7
7
  class Command # rubocop:disable ClassLength
8
8
  include DoSnapshot::Helpers
9
9
 
10
+ RESET_OPTIONS = [:droplets, :exclude, :only, :keep, :quiet,
11
+ :stop, :clean, :timeout, :shutdown, :delay,
12
+ :protocol, :threads, :api]
13
+
10
14
  def initialize(*args)
11
15
  load_options(*args)
12
16
  end
@@ -21,6 +25,7 @@ module DoSnapshot
21
25
  end
22
26
 
23
27
  def fail_power_off(e)
28
+ return unless shutdown
24
29
  return unless e && e.id
25
30
  api.start_droplet(e.id)
26
31
  rescue
@@ -35,12 +40,13 @@ module DoSnapshot
35
40
  end
36
41
 
37
42
  def reset_options
38
- [:droplets, :exclude, :only, :keep, :quiet, :stop, :clean, :timeout, :delay, :protocol, :threads, :api].each do |key|
43
+ RESET_OPTIONS.each do |key|
39
44
  send("#{key}=", nil)
40
45
  end
41
46
  end
42
47
 
43
48
  def stop_droplet(droplet)
49
+ return true unless shutdown
44
50
  logger.debug 'Shutting down droplet.'
45
51
  api.stop_droplet(droplet.id) unless droplet.status.include? 'off'
46
52
  true
@@ -49,10 +55,15 @@ module DoSnapshot
49
55
  false
50
56
  end
51
57
 
58
+ def fail_if_shutdown(droplet)
59
+ return unless shutdown
60
+ fail DropletPowerError.new(droplet.id), droplet.name unless api.inactive?(droplet.id)
61
+ end
62
+
52
63
  # Trying to create a snapshot.
53
64
  #
54
65
  def create_snapshot(droplet) # rubocop:disable MethodLength,Metrics/AbcSize
55
- fail DropletPowerError.new(droplet.id), droplet.name unless api.inactive?(droplet.id)
66
+ fail_if_shutdown(droplet)
56
67
 
57
68
  logger.info "Start creating snapshot for droplet id: #{droplet.id} name: #{droplet.name}."
58
69
 
@@ -104,7 +115,7 @@ module DoSnapshot
104
115
  protected
105
116
 
106
117
  attr_accessor :droplets, :exclude, :only
107
- attr_accessor :keep, :quiet, :stop, :stop_by_power, :clean, :timeout, :delay, :protocol
118
+ attr_accessor :keep, :quiet, :shutdown, :stop, :stop_by_power, :clean, :timeout, :delay, :protocol
108
119
 
109
120
  attr_writer :threads, :api
110
121
 
@@ -2,5 +2,5 @@
2
2
  # Current version
3
3
  #
4
4
  module DoSnapshot
5
- VERSION = '0.6.2'
5
+ VERSION = '0.6.3'
6
6
  end
@@ -75,6 +75,14 @@ RSpec.describe DoSnapshot::CLI do
75
75
  attribute_eq 'stop', false
76
76
  end
77
77
 
78
+ it 'with shutdown' do
79
+ attribute_eq 'shutdown', true
80
+ end
81
+
82
+ it 'with no shutdown' do
83
+ attribute_eq 'shutdown', false
84
+ end
85
+
78
86
  it 'with stop by power' do
79
87
  attribute_eq 'stop_by_power', true
80
88
  end
@@ -113,7 +113,7 @@ RSpec.describe DoSnapshot::Command do
113
113
  describe '.stop_droplet by power status' do
114
114
  it 'when raised with error' do
115
115
  stub_droplet_stop_fail(droplet_id)
116
- load_options(stop_by_power: true)
116
+ load_options(stop_by_power: true, shutdown: true)
117
117
  droplet = cmd.api.droplet droplet_id
118
118
  expect { cmd.stop_droplet(droplet) }
119
119
  .not_to raise_error
@@ -124,7 +124,17 @@ RSpec.describe DoSnapshot::Command do
124
124
  it 'when stopped' do
125
125
  stub_droplet_inactive(droplet_id)
126
126
  stub_droplet_stop(droplet_id)
127
- load_options(stop_by_power: true)
127
+ load_options(stop_by_power: true, shutdown: true)
128
+ droplet = cmd.api.droplet droplet_id
129
+ expect { cmd.stop_droplet(droplet) }
130
+ .not_to raise_error
131
+ expect(cmd.stop_droplet(droplet))
132
+ .to be_truthy
133
+ end
134
+
135
+ it 'when nothing' do
136
+ stub_droplet(droplet_id)
137
+ load_options(stop_by_power: true, shutdown: false)
128
138
  droplet = cmd.api.droplet droplet_id
129
139
  expect { cmd.stop_droplet(droplet) }
130
140
  .not_to raise_error
@@ -154,6 +164,16 @@ RSpec.describe DoSnapshot::Command do
154
164
  expect(cmd.stop_droplet(droplet))
155
165
  .to be_truthy
156
166
  end
167
+
168
+ it 'when nothing' do
169
+ stub_droplet(droplet_id)
170
+ load_options(shutdown: false)
171
+ droplet = cmd.api.droplet droplet_id
172
+ expect { cmd.stop_droplet(droplet) }
173
+ .not_to raise_error
174
+ expect(cmd.stop_droplet(droplet))
175
+ .to be_truthy
176
+ end
157
177
  end
158
178
 
159
179
  describe '.create_snapshot' do
@@ -176,6 +196,18 @@ RSpec.describe DoSnapshot::Command do
176
196
  .not_to raise_error
177
197
  end
178
198
 
199
+ it 'when snapshot is created with no shutdown' do
200
+ stub_droplet(droplet_id)
201
+ stub_droplet_snapshot(droplet_id, snapshot_name)
202
+ load_options(shutdown: false)
203
+ droplet = cmd.api.droplet droplet_id
204
+ cmd.create_snapshot(droplet)
205
+ expect(DoSnapshot.logger.buffer)
206
+ .not_to include "Droplet id: #{droplet_id} must be Powered Off!"
207
+ expect { cmd.create_snapshot(droplet) }
208
+ .not_to raise_error
209
+ end
210
+
179
211
  it 'when droplet is running' do
180
212
  stub_droplet(droplet_id)
181
213
  load_options
@@ -191,16 +223,25 @@ RSpec.describe DoSnapshot::Command do
191
223
  describe '.fail_power_off' do
192
224
  it 'when success' do
193
225
  stub_droplet_inactive(droplet_id)
194
-
226
+ load_options(shutdown: true)
195
227
  expect { cmd.fail_power_off(DoSnapshot::DropletShutdownError.new(droplet_id)) }
196
228
  .not_to raise_error
197
229
  expect(DoSnapshot.logger.buffer)
198
230
  .to include "Droplet id: #{droplet_id} is requested for Power On."
199
231
  end
200
232
 
201
- it 'with request error' do
233
+ it 'not rescue when shutdown is true' do
202
234
  stub_droplet_fail(droplet_id)
235
+ load_options(shutdown: false)
236
+ expect { cmd.fail_power_off(DoSnapshot::SnapshotCreateError.new(droplet_id)) }
237
+ .not_to raise_error
238
+ expect(DoSnapshot.logger.buffer)
239
+ .to include "Droplet id: #{droplet_id} is Failed to Snapshot."
240
+ end
203
241
 
242
+ it 'with request error' do
243
+ stub_droplet_fail(droplet_id)
244
+ load_options(shutdown: true)
204
245
  expect { cmd.fail_power_off(DoSnapshot::DropletShutdownError.new(droplet_id)) }
205
246
  .to raise_error(DoSnapshot::DropletFindError)
206
247
  expect(DoSnapshot.logger.buffer)
@@ -212,7 +253,7 @@ RSpec.describe DoSnapshot::Command do
212
253
  it 'with start error' do
213
254
  stub_droplet_inactive(droplet_id)
214
255
  stub_droplet_start_done(droplet_id)
215
-
256
+ load_options(shutdown: true)
216
257
  expect { cmd.fail_power_off(DoSnapshot::DropletShutdownError.new(droplet_id)) }
217
258
  .not_to raise_error
218
259
  expect(DoSnapshot.logger.buffer)
@@ -109,6 +109,24 @@ RSpec.describe DoSnapshot::Runner, type: :aruba do
109
109
  expect(all_stdout).to include(t_snapshot_created(snapshot_name))
110
110
  end
111
111
 
112
+ it 'with shutdown' do
113
+ attribute_eq 'shutdown', true
114
+
115
+ expect(last_command).to have_exit_status(0)
116
+ expect(all_stdout).to include(t_droplet_shutdown)
117
+ expect(all_stdout).to include(t_wait_until_create)
118
+ expect(all_stdout).to include(t_snapshot_created(snapshot_name))
119
+ end
120
+
121
+ it 'with no shutdown' do
122
+ attribute_eq 'shutdown', false
123
+
124
+ expect(last_command).to have_exit_status(0)
125
+ expect(all_stdout).not_to include(t_droplet_shutdown)
126
+ expect(all_stdout).to include(t_wait_until_create)
127
+ expect(all_stdout).to include(t_snapshot_created(snapshot_name))
128
+ end
129
+
112
130
  it 'with stop by power' do
113
131
  attribute_eq 'stop_by_power', true
114
132
 
@@ -19,7 +19,7 @@ RSpec.shared_context 'environment' do
19
19
  let(:cli_keys) { Thor::CoreExt::HashWithIndifferentAccess.new(digital_ocean_access_token: access_token) }
20
20
  let(:cli_keys_other) { Thor::CoreExt::HashWithIndifferentAccess.new(digital_ocean_access_token: 'NOTTOK') }
21
21
  let(:snapshot_name) { "example.com_#{DateTime.now.strftime('%Y_%m_%d')}" }
22
- let(:default_options) { Hash[protocol: 2, only: %w( 100823 ), exclude: %w(), keep: 3, stop: false, trace: true, clean: true, delay: 0, timeout: 600] }
22
+ let(:default_options) { Hash[protocol: 2, only: %w( 100823 ), exclude: %w(), keep: 3, stop: false, trace: true, clean: true, delay: 0, shutdown: true, timeout: 600] }
23
23
  let(:default_options_cli) { default_options.reject { |key, _| %w( droplets threads ).include?(key.to_s) } }
24
24
  let(:no_exclude) { [] }
25
25
  let(:exclude) { %w( 100824 100825 ) }
@@ -31,6 +31,7 @@ RSpec.shared_context 'environment' do
31
31
  let(:no_quiet) { false }
32
32
  let(:clean) { true }
33
33
  let(:no_clean) { false }
34
+ let(:shutdown) { true }
34
35
  let(:timeout) { 600 }
35
36
  let(:delay) { 0 }
36
37
  let(:log_path) { "#{project_path}/log/test.log" }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: do_snapshot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Merkulov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-09 00:00:00.000000000 Z
11
+ date: 2016-08-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: barge