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 +4 -4
- data/README.md +9 -4
- data/lib/do_snapshot/adapter/digitalocean_v2.rb +1 -1
- data/lib/do_snapshot/cli.rb +5 -1
- data/lib/do_snapshot/command.rb +14 -3
- data/lib/do_snapshot/version.rb +1 -1
- data/spec/do_snapshot/cli_spec.rb +8 -0
- data/spec/do_snapshot/command_spec.rb +46 -5
- data/spec/do_snapshot/runner_spec.rb +18 -0
- data/spec/shared/environment.rb +2 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ee1fb26e08febbd07bd95db15ede7e27288c6ac
|
4
|
+
data.tar.gz: e94d18d396f7afe4a2746b7d5f26ab4bf162cc1e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
- [
|
91
|
-
|
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] #
|
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].
|
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
|
|
data/lib/do_snapshot/cli.rb
CHANGED
@@ -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:
|
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 ),
|
data/lib/do_snapshot/command.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
|
data/lib/do_snapshot/version.rb
CHANGED
@@ -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 '
|
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
|
|
data/spec/shared/environment.rb
CHANGED
@@ -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.
|
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-
|
11
|
+
date: 2016-08-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: barge
|