do_snapshot 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/README.md +51 -21
- data/lib/do_snapshot/api.rb +3 -3
- data/lib/do_snapshot/cli.rb +2 -2
- data/lib/do_snapshot/command.rb +12 -4
- data/lib/do_snapshot/distribution.rb +13 -0
- data/lib/do_snapshot/log.rb +1 -1
- data/lib/do_snapshot/version.rb +1 -1
- data/spec/do_snapshot/api_spec.rb +6 -0
- data/spec/do_snapshot/cli_spec.rb +18 -1
- data/spec/do_snapshot/command_spec.rb +17 -18
- data/spec/do_snapshots_spec.rb +7 -1
- data/spec/shared/environment.rb +12 -26
- data/spec/spec_helper.rb +2 -0
- metadata +76 -57
- data/.gitignore +0 -28
- data/.rubocop.yml +0 -14
- data/.ruby-version +0 -1
- data/.travis.yml +0 -10
- data/Gemfile +0 -4
- data/LICENSE.txt +0 -22
- data/Rakefile +0 -7
- data/do_snapshot.gemspec +0 -33
- data/log/.keep +0 -0
- data/tmp/.keep +0 -0
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
YmVmZGFjMzIwNjZmZDY1NjA3M2QzMDI0OGFmZDJkYTk3NzM0NmE2ZA==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 95ce0ffdfe696ae7a5cce1b334dd49a5d250f1bc
|
4
|
+
data.tar.gz: cbebe31ada54228fcd5b7f0cb642b7e37cccf0bd
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
Mzc0MTUxZWUzODFkYjBkMGIyNGIwOWU3MGY2Y2EzNzJmNDgwNzQ1M2E2NWYx
|
11
|
-
MjBkYWY2MTIxNTNmMWZmN2U1MDMzNjBkNGIxODQwOWNiZGI5MmQ=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
MTY2YmI2NWQ1ZWYxZWYwMGNjMjYzMzk1NjU5M2Q2YjM0NGNjNjU4ZGVjOTc2
|
14
|
-
YWZjZWEzMDYzZDE0Yjk4Njg3ZWEyNDQwZDVmODEzN2UwNjk1OTYyZmI4NGJj
|
15
|
-
MGQ4NGQzMGZhNjJhYTZiMzcyOGZhNjNlNWZmNTJjNjNiNDQwMTg=
|
6
|
+
metadata.gz: f4b1a3c9f608d28cf411cbed0dad3929eaabb65f43f6030e071d6e952f3323ab6d4edb5dac99e44fdccae8a3cdacc71958a7f831f8c65a9b1e1eecd1d1445347
|
7
|
+
data.tar.gz: cec0fd4b44bd7dad64e9f038947bdbd3f14641169f5152ef07fef1ead965f1e1d082f6f81eea6c69900bd32ecb9e04028f9b76bb802d48750100f83bab561a7d
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# DoSnapshot
|
1
|
+
# DoSnapshot CLI
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/do_snapshot.svg)](http://badge.fury.io/rb/do_snapshot)
|
4
4
|
[![Build Status](https://travis-ci.org/merqlove/do_snapshot.svg?branch=master)](https://travis-ci.org/merqlove/do_snapshot)
|
@@ -7,45 +7,67 @@
|
|
7
7
|
[![Inline docs](http://inch-ci.org/github/merqlove/do_snapshot.png?branch=master)](http://inch-ci.org/github/merqlove/do_snapshot)
|
8
8
|
[![Code Climate](https://codeclimate.com/github/merqlove/do_snapshot.png)](https://codeclimate.com/github/merqlove/do_snapshot)
|
9
9
|
|
10
|
-
|
10
|
+
Use this tool to backup DigitalOcean droplet's via snapshot method, on the fly!
|
11
11
|
|
12
12
|
Here some features:
|
13
13
|
|
14
14
|
- Multiple threads out of the box. No matter how much droplet's you have.
|
15
|
-
- Auto-
|
16
|
-
-
|
15
|
+
- Snapshots Auto-Cleanup.
|
16
|
+
- Auto-Boot Droplet back if Snapshot Event is failed or bad connection exception.
|
17
|
+
- Binary special for cron and command-line. Homebrew, Standalone installers.
|
17
18
|
- Mail notifications when fail or maximum of snapshots is reached for one or multiple droplets.
|
18
19
|
- Custom mail settings (You can set [Pony](https://github.com/benprew/pony) mail settings).
|
19
20
|
- Stop mode (when you don't want to create new snapshots when maximum is reached).
|
20
|
-
- Timeout for
|
21
|
+
- Timeout option for long requests or uncaught loops. By default it 600 seconds, but you can change it by hand.
|
21
22
|
- Logging into selected directory.
|
22
23
|
- Verbose mode for research.
|
23
24
|
- Quiet mode for silence.
|
24
25
|
|
25
|
-
|
26
|
+
## Compatibility
|
26
27
|
|
27
|
-
|
28
|
-
- `Thor` for CLI.
|
29
|
-
- `Pony` for mail notifications.
|
28
|
+
Ruby versions: 1.9.3 and higher. JRuby in 1.9 mode is also supported.
|
30
29
|
|
31
|
-
|
30
|
+
![DoSnaphot example](https://raw.githubusercontent.com/merqlove/do_snapshot/assets/example.png)
|
31
|
+
|
32
|
+
### You can ask me, "Why you made this tool?"
|
32
33
|
|
33
|
-
|
34
|
+
- First. I needed stable tool, which can provide for me automatic Snapshot feature for all of my Droplets via Cron planner.
|
35
|
+
- I don't want to think how much snapshots for each droplet i have.
|
36
|
+
- I don't wont to sleep when my droplets Offline!!! And i wanted tool which can Staryt
|
37
|
+
- Also i want to understand what's going on if there some error. Mail is my choice. But logs also good.
|
38
|
+
- And ... sure ;) We want to do it fast as rocket! :)
|
39
|
+
- more more more...
|
40
|
+
- So this tool can save a lot of time for people.
|
34
41
|
|
35
42
|
## Installation
|
36
43
|
|
37
|
-
|
44
|
+
Install it yourself as:
|
38
45
|
|
39
|
-
gem
|
46
|
+
$ gem install do_snapshot
|
47
|
+
|
48
|
+
For **OSX** users ([Homebrew Tap](http://github.com/merqlove/do_snapshot/tap)):
|
40
49
|
|
41
|
-
|
50
|
+
$ brew tap merqlove/do_snapshot/tap && brew install do_snapshot
|
51
|
+
|
52
|
+
$ do_snapshot -V
|
53
|
+
|
54
|
+
Standalone pack for **Unix/Linux** users: [Download](https://assets.merqlove.ru.s3.amazonaws.com/do_snapshot/dosnapshot.tgz)
|
55
|
+
|
56
|
+
$ wget https://assets.merqlove.ru.s3.amazonaws.com/do_snapshot/do_snapshot.tgz # if not done.
|
57
|
+
|
58
|
+
# Example Install into /usr/local
|
59
|
+
|
60
|
+
$ tar -xzf do_snapshot.tgz /usr/local/ && ln -s /usr/local/do_snapshot/bin/do_snapshot /usr/local/bin/do_snapshot
|
61
|
+
$ do_snapshot help
|
42
62
|
|
43
|
-
|
63
|
+
Or add this line to Gemfile:
|
44
64
|
|
45
|
-
|
65
|
+
gem 'do_snapshot'
|
46
66
|
|
47
|
-
|
67
|
+
And then execute:
|
48
68
|
|
69
|
+
$ bundle
|
70
|
+
|
49
71
|
## Usage
|
50
72
|
|
51
73
|
First you may need to set DigitalOcean API keys:
|
@@ -57,7 +79,7 @@ If you want to set keys without environment, than set it via options when you ru
|
|
57
79
|
|
58
80
|
$ do_snapshot --digital-ocean-client-id YOURLONGAPICLIENTID --digital-ocean-api-key YOURLONGAPIKEY
|
59
81
|
|
60
|
-
|
82
|
+
### How-To
|
61
83
|
|
62
84
|
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.
|
63
85
|
|
@@ -75,16 +97,18 @@ Keep latest 5 snapshots, send mail notification instead of creating new one:
|
|
75
97
|
|
76
98
|
$ do_snapshot --keep 10 --stop --mail to:yourmail@example.com
|
77
99
|
|
100
|
+
![DoSnapshot Safe Mode Example](https://raw.githubusercontent.com/merqlove/do_snapshot/assets/safe_mode.png)
|
101
|
+
|
78
102
|
E-mail notifications disabled out of the box.
|
79
103
|
For working mailer you need to set e-mail settings via run options.
|
80
104
|
|
81
105
|
--mail to:mail@somehost.com from:from@host.com --smtp address:smtp.gmail.com port:25 user_name:someuser password:somepassword
|
82
106
|
|
83
|
-
|
107
|
+
### Cron example
|
84
108
|
|
85
109
|
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
|
86
110
|
|
87
|
-
|
111
|
+
### Real world example
|
88
112
|
|
89
113
|
$ bin/do_snapshot --only 123456 -k 3 -c -m to:TO from:FROM -t address:HOST user_name:LOGIN password:PASSWORD port:2525 -v
|
90
114
|
|
@@ -119,7 +143,7 @@ For working mailer you need to set e-mail settings via run options.
|
|
119
143
|
-d, [--delay=5] # Delay between snapshot operation status requests.
|
120
144
|
# Default: 10
|
121
145
|
[--timeout=250] # Timeout in sec's for events like Power Off or Create Snapshot.
|
122
|
-
# Default:
|
146
|
+
# Default: 600
|
123
147
|
-m, [--mail=to:yourmail@example.com] # Receive mail if fail or maximum is reached.
|
124
148
|
-t, [--smtp=user_name:yourmail@example.com password:password] # SMTP options.
|
125
149
|
-l, [--log=/Users/someone/.do_snapshot/main.log] # Log file path. By default logging is disabled.
|
@@ -135,6 +159,12 @@ For working mailer you need to set e-mail settings via run options.
|
|
135
159
|
|
136
160
|
You can optionally specify parameters to select or exclude some droplets.
|
137
161
|
|
162
|
+
## Dependencies:
|
163
|
+
|
164
|
+
- [Thor](https://github.com/erikhuda/thor) for CLI.
|
165
|
+
- [Digitalocean](https://github.com/scottmotte/digitalocean) for API requests.
|
166
|
+
- [Pony](https://github.com/benprew/pony) for mail notifications.
|
167
|
+
|
138
168
|
## Contributing
|
139
169
|
|
140
170
|
1. Fork it ( https://github.com/merqlove/do_snapshot/fork )
|
data/lib/do_snapshot/api.rb
CHANGED
@@ -109,15 +109,15 @@ module DoSnapshot
|
|
109
109
|
|
110
110
|
# Waiting for event exit
|
111
111
|
def wait_event(id)
|
112
|
-
time = Time.now
|
113
|
-
sleep
|
112
|
+
time = Time.now
|
113
|
+
sleep(delay) until get_event_status(id, time)
|
114
114
|
end
|
115
115
|
|
116
116
|
# Looking for event status.
|
117
117
|
# Before snapshot we to know that machine has powered off.
|
118
118
|
#
|
119
119
|
def get_event_status(id, time)
|
120
|
-
return true if (Time.now.to_f - time) > timeout
|
120
|
+
return true if (Time.now.to_f - time.to_f) > timeout
|
121
121
|
event = Digitalocean::Event.find(id)
|
122
122
|
fail event.message unless event.status.include?('OK')
|
123
123
|
# noinspection RubyResolve,RubyResolve
|
data/lib/do_snapshot/cli.rb
CHANGED
@@ -92,7 +92,7 @@ module DoSnapshot
|
|
92
92
|
desc: 'Delay between snapshot operation status requests.'
|
93
93
|
method_option :timeout,
|
94
94
|
type: :numeric,
|
95
|
-
default:
|
95
|
+
default: 600,
|
96
96
|
banner: '250',
|
97
97
|
desc: 'Timeout in sec\'s for events like Power Off or Create Snapshot.'
|
98
98
|
method_option :mail,
|
@@ -137,7 +137,7 @@ module DoSnapshot
|
|
137
137
|
desc: 'DIGITAL_OCEAN_API_KEY. if you can\'t use environment.'
|
138
138
|
|
139
139
|
def snap
|
140
|
-
Command.snap options, %w( log trace digital_ocean_client_id digital_ocean_api_key )
|
140
|
+
Command.snap options, %w( log mail smtp trace digital_ocean_client_id digital_ocean_api_key )
|
141
141
|
rescue => e
|
142
142
|
Command.fail_power_off(e) if [SnapshotCreateError, DropletShutdownError].include?(e.class)
|
143
143
|
Log.error e.message
|
data/lib/do_snapshot/command.rb
CHANGED
@@ -11,7 +11,7 @@ module DoSnapshot
|
|
11
11
|
return unless options
|
12
12
|
|
13
13
|
options.each_pair do |key, option|
|
14
|
-
send("#{key}=", option) unless skip.include?
|
14
|
+
send("#{key}=", option) unless skip.include?(key)
|
15
15
|
end
|
16
16
|
|
17
17
|
Log.info 'Start performing operations'
|
@@ -30,10 +30,10 @@ module DoSnapshot
|
|
30
30
|
|
31
31
|
protected
|
32
32
|
|
33
|
-
attr_accessor :droplets, :
|
34
|
-
attr_accessor :
|
33
|
+
attr_accessor :droplets, :exclude, :only
|
34
|
+
attr_accessor :keep, :quiet, :stop, :clean
|
35
35
|
|
36
|
-
attr_writer :notify, :threads, :api
|
36
|
+
attr_writer :notify, :delay, :timeout, :threads, :api
|
37
37
|
|
38
38
|
def api
|
39
39
|
@api ||= API.new(delay: delay, timeout: timeout)
|
@@ -47,6 +47,14 @@ module DoSnapshot
|
|
47
47
|
@threads ||= []
|
48
48
|
end
|
49
49
|
|
50
|
+
def timeout
|
51
|
+
@timeout ||= 600
|
52
|
+
end
|
53
|
+
|
54
|
+
def delay
|
55
|
+
@delay ||= 10
|
56
|
+
end
|
57
|
+
|
50
58
|
# Working with list of droplets.
|
51
59
|
#
|
52
60
|
def work_with_droplets
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module DoSnapshot
|
3
|
+
# Distributive files
|
4
|
+
# Used part of Heroku script https://github.com/heroku/heroku
|
5
|
+
#
|
6
|
+
module Distribution
|
7
|
+
def self.files
|
8
|
+
Dir[File.expand_path('../../../{bin,lib}/**/*', __FILE__)].select do |file|
|
9
|
+
File.file?(file)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/do_snapshot/log.rb
CHANGED
data/lib/do_snapshot/version.rb
CHANGED
@@ -210,9 +210,15 @@ describe DoSnapshot::API do
|
|
210
210
|
.to have_been_made
|
211
211
|
end
|
212
212
|
end
|
213
|
+
|
214
|
+
after(:all) do
|
215
|
+
WebMock.reset!
|
216
|
+
end
|
213
217
|
end
|
214
218
|
|
215
219
|
before(:each) do
|
216
220
|
log.buffer = %w()
|
221
|
+
log.verbose = false
|
222
|
+
log.quiet = true
|
217
223
|
end
|
218
224
|
end
|
@@ -167,7 +167,24 @@ describe DoSnapshot::CLI do
|
|
167
167
|
command.send('api=', api.new(options))
|
168
168
|
end
|
169
169
|
|
170
|
+
before(:each) do
|
171
|
+
$stdout.sync = true
|
172
|
+
$stderr.sync = true
|
173
|
+
|
174
|
+
@cli = cli.new
|
175
|
+
|
176
|
+
# Keep track of the old stderr / out
|
177
|
+
@orig_stderr = $stderr
|
178
|
+
@orig_stdout = $stdout
|
179
|
+
|
180
|
+
# Make them strings so we can manipulate and compare.
|
181
|
+
$stderr = StringIO.new
|
182
|
+
$stdout = StringIO.new
|
183
|
+
end
|
184
|
+
|
170
185
|
after(:each) do
|
171
|
-
#
|
186
|
+
# Reassign the stderr / out so rspec can have it back.
|
187
|
+
$stderr = @orig_stderr
|
188
|
+
$stdout = @orig_stdout
|
172
189
|
end
|
173
190
|
end
|
@@ -5,11 +5,12 @@ describe DoSnapshot::Command do
|
|
5
5
|
include_context 'spec'
|
6
6
|
include_context 'uri_helpers'
|
7
7
|
|
8
|
+
subject(:cmd) { DoSnapshot::Command }
|
8
9
|
subject(:log) { DoSnapshot::Log }
|
9
10
|
|
10
11
|
describe '.snap' do
|
11
12
|
context 'when success' do
|
12
|
-
it 'sends
|
13
|
+
it 'sends message' do
|
13
14
|
expect { snap_runner }
|
14
15
|
.not_to raise_error
|
15
16
|
expect(log.buffer)
|
@@ -18,7 +19,7 @@ describe DoSnapshot::Command do
|
|
18
19
|
end
|
19
20
|
|
20
21
|
context 'when snapshot not cleanup' do
|
21
|
-
it 'sends
|
22
|
+
it 'sends message' do
|
22
23
|
stub_image_destroy_fail(image_id)
|
23
24
|
stub_image_destroy_fail(image_id2)
|
24
25
|
|
@@ -37,7 +38,7 @@ describe DoSnapshot::Command do
|
|
37
38
|
end
|
38
39
|
|
39
40
|
context 'when failed to list droplets' do
|
40
|
-
it 'raised with
|
41
|
+
it 'raised with error' do
|
41
42
|
stub_droplets_fail
|
42
43
|
|
43
44
|
expect { snap_runner }
|
@@ -46,8 +47,9 @@ describe DoSnapshot::Command do
|
|
46
47
|
end
|
47
48
|
|
48
49
|
# TODO: MUST HAVE! Now when this two works others can fail...
|
50
|
+
# I think it's threading problem with RSpec
|
49
51
|
# context 'when droplet failed for shutdown' do
|
50
|
-
# it 'raised with
|
52
|
+
# it 'raised with error' do
|
51
53
|
# fail = stub_droplet_stop_fail(droplet_id)
|
52
54
|
#
|
53
55
|
# expect { snap_runner }
|
@@ -56,15 +58,16 @@ describe DoSnapshot::Command do
|
|
56
58
|
# remove_request_stub(fail)
|
57
59
|
# end
|
58
60
|
# end
|
59
|
-
|
61
|
+
|
60
62
|
# context 'when no snapshot created' do
|
61
|
-
# it 'raised with
|
62
|
-
# no_snapshot =
|
63
|
+
# it 'raised with error' do
|
64
|
+
# # no_snapshot =
|
65
|
+
# stub_droplet_snapshot_fail(droplet_id, snapshot_name)
|
63
66
|
#
|
64
67
|
# expect { snap_runner }
|
65
68
|
# .to raise_error(DoSnapshot::SnapshotCreateError)
|
66
69
|
#
|
67
|
-
# remove_request_stub(no_snapshot)
|
70
|
+
# # remove_request_stub(no_snapshot)
|
68
71
|
# end
|
69
72
|
# end
|
70
73
|
end
|
@@ -73,7 +76,7 @@ describe DoSnapshot::Command do
|
|
73
76
|
it 'when success' do
|
74
77
|
stub_droplet_inactive(droplet_id)
|
75
78
|
|
76
|
-
expect {
|
79
|
+
expect { cmd.fail_power_off(DoSnapshot::DropletShutdownError.new(droplet_id)) }
|
77
80
|
.not_to raise_error
|
78
81
|
expect(log.buffer)
|
79
82
|
.to include 'Power On has been requested.'
|
@@ -82,7 +85,7 @@ describe DoSnapshot::Command do
|
|
82
85
|
it 'with request error' do
|
83
86
|
stub_droplet_fail(droplet_id)
|
84
87
|
|
85
|
-
expect {
|
88
|
+
expect { cmd.fail_power_off(DoSnapshot::DropletShutdownError.new(droplet_id)) }
|
86
89
|
.to raise_error
|
87
90
|
expect(log.buffer)
|
88
91
|
.to include 'Droplet id: 100823 is Failed to Power Off.'
|
@@ -95,27 +98,23 @@ describe DoSnapshot::Command do
|
|
95
98
|
stub_droplet_start_fail(droplet_id)
|
96
99
|
stub_event_fail(event_id)
|
97
100
|
|
98
|
-
expect {
|
101
|
+
expect { cmd.fail_power_off(DoSnapshot::DropletShutdownError.new(droplet_id)) }
|
99
102
|
.not_to raise_error
|
100
103
|
expect(log.buffer)
|
101
104
|
.to include 'Power On failed to request.'
|
102
105
|
end
|
103
106
|
end
|
104
107
|
|
105
|
-
after(:each) do
|
106
|
-
# WebMock.reset!
|
107
|
-
stub_cleanup
|
108
|
-
end
|
109
|
-
|
110
108
|
before(:each) do
|
111
|
-
@cmd = DoSnapshot::Command
|
109
|
+
# @cmd = DoSnapshot::Command
|
112
110
|
stub_all_api(nil, true)
|
113
111
|
log.buffer = %w()
|
112
|
+
log.verbose = false
|
114
113
|
log.quiet = true
|
115
114
|
end
|
116
115
|
|
117
116
|
def snap_runner(options = nil)
|
118
117
|
options ||= default_options
|
119
|
-
|
118
|
+
cmd.snap(options, [:log, :mail, :smtp, :trace, :digital_ocean_client_id, :digital_ocean_api_key])
|
120
119
|
end
|
121
120
|
end
|
data/spec/do_snapshots_spec.rb
CHANGED
@@ -4,7 +4,7 @@ require 'spec_helper'
|
|
4
4
|
describe DoSnapshot do
|
5
5
|
include_context 'spec'
|
6
6
|
|
7
|
-
subject(:log)
|
7
|
+
subject(:log) { DoSnapshot::Log }
|
8
8
|
|
9
9
|
describe DoSnapshot::DropletFindError do
|
10
10
|
subject(:error) { described_class }
|
@@ -55,4 +55,10 @@ describe DoSnapshot do
|
|
55
55
|
.to include "Droplet id: #{droplet_id} is Failed to Snapshot."
|
56
56
|
end
|
57
57
|
end
|
58
|
+
|
59
|
+
before(:each) do
|
60
|
+
log.buffer = %w()
|
61
|
+
log.verbose = false
|
62
|
+
log.quiet = true
|
63
|
+
end
|
58
64
|
end
|
data/spec/shared/environment.rb
CHANGED
@@ -12,7 +12,7 @@ shared_context 'spec' do
|
|
12
12
|
let(:image_id2) { '5019903' }
|
13
13
|
let(:cli_keys) { Thor::CoreExt::HashWithIndifferentAccess.new(digital_ocean_client_id: 'NOTFOO', digital_ocean_client_bar: 'NOTBAR') }
|
14
14
|
let(:snapshot_name) { "foo_#{DateTime.now.strftime('%Y_%m_%d')}" }
|
15
|
-
let(:default_options) { Hash[only: %w( 100823 ), exclude: %w(), keep: 3, trace: true, clean: true, delay: 0, timeout:
|
15
|
+
let(:default_options) { Hash[only: %w( 100823 ), exclude: %w(), keep: 3, trace: true, clean: true, delay: 0, timeout: 600, droplets: nil, threads: []] }
|
16
16
|
let(:no_exclude) { [] }
|
17
17
|
let(:exclude) { %w( 100824 100825 ) }
|
18
18
|
let(:no_only) { [] }
|
@@ -23,7 +23,7 @@ shared_context 'spec' do
|
|
23
23
|
let(:no_quiet) { false }
|
24
24
|
let(:clean) { true }
|
25
25
|
let(:no_clean) { false }
|
26
|
-
let(:timeout) {
|
26
|
+
let(:timeout) { 600 }
|
27
27
|
let(:delay) { 0 }
|
28
28
|
let(:mail_options) { Thor::CoreExt::HashWithIndifferentAccess.new(to: 'mail@somehost.com', from: 'from@host.com') }
|
29
29
|
let(:smtp_options) { Thor::CoreExt::HashWithIndifferentAccess.new(address: 'smtp.gmail.com', port: '25', user_name: 'someuser', password: 'somepassword') }
|
@@ -41,30 +41,6 @@ shared_context 'spec' do
|
|
41
41
|
let(:snapshot_uri) { "#{droplets_api_base}/[id]/snapshot/?name=[name]&#{keys_uri}" }
|
42
42
|
let(:event_find_uri) { "#{events_api_base}/[id]/?#{keys_uri}" }
|
43
43
|
|
44
|
-
before(:each) do
|
45
|
-
$stdout.sync = true
|
46
|
-
$stderr.sync = true
|
47
|
-
|
48
|
-
ENV['DIGITAL_OCEAN_API_KEY'] = api_key
|
49
|
-
ENV['DIGITAL_OCEAN_CLIENT_ID'] = client_key
|
50
|
-
|
51
|
-
@cli = DoSnapshot::CLI.new
|
52
|
-
|
53
|
-
# Keep track of the old stderr / out
|
54
|
-
@orig_stderr = $stderr
|
55
|
-
@orig_stdout = $stdout
|
56
|
-
|
57
|
-
# Make them strings so we can manipulate and compare.
|
58
|
-
$stderr = StringIO.new
|
59
|
-
$stdout = StringIO.new
|
60
|
-
end
|
61
|
-
|
62
|
-
after(:each) do
|
63
|
-
# Reassign the stderr / out so rspec can have it back.
|
64
|
-
$stderr = @orig_stderr
|
65
|
-
$stdout = @orig_stdout
|
66
|
-
end
|
67
|
-
|
68
44
|
def stub_all_api(droplets = nil, active = false) # rubocop:disable MethodLength
|
69
45
|
drops = []
|
70
46
|
droplets ||= [droplet_id]
|
@@ -111,4 +87,14 @@ shared_context 'spec' do
|
|
111
87
|
before(:all) do
|
112
88
|
WebMock.reset!
|
113
89
|
end
|
90
|
+
|
91
|
+
after(:all) do
|
92
|
+
# sleep(1)
|
93
|
+
end
|
94
|
+
|
95
|
+
before(:each) do
|
96
|
+
# stub_cleanup
|
97
|
+
ENV['DIGITAL_OCEAN_API_KEY'] = api_key
|
98
|
+
ENV['DIGITAL_OCEAN_CLIENT_ID'] = client_key
|
99
|
+
end
|
114
100
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,169 +1,197 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: do_snapshot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexander Merkulov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: digitalocean
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: thor
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.19
|
33
|
+
version: '0.19'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.19
|
40
|
+
version: '0.19'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: pony
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 1.1
|
47
|
+
version: '1.1'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - ~>
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 1.1
|
54
|
+
version: '1.1'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 0.8.7
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 0.8.7
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: json
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: rubocop
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
89
|
+
version: '0.24'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
96
|
+
version: '0.24'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rspec-core
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: 3.0
|
103
|
+
version: '3.0'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: 3.0
|
110
|
+
version: '3.0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: rspec-expectations
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- -
|
115
|
+
- - ">="
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 3.0
|
117
|
+
version: '3.0'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- -
|
122
|
+
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 3.0
|
124
|
+
version: '3.0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: rspec-mocks
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
|
-
- -
|
129
|
+
- - ">="
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: 3.0
|
131
|
+
version: '3.0'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
|
-
- -
|
136
|
+
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: 3.0
|
138
|
+
version: '3.0'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: webmock
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
|
-
- -
|
143
|
+
- - ">="
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version: 1.18
|
145
|
+
version: '1.18'
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
|
-
- -
|
150
|
+
- - ">="
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version: 1.18
|
152
|
+
version: '1.18'
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
154
|
name: coveralls
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
156
156
|
requirements:
|
157
|
-
- -
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0.7'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0.7'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: rubyzip
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
158
172
|
- !ruby/object:Gem::Version
|
159
|
-
version: 0
|
173
|
+
version: '0'
|
160
174
|
type: :development
|
161
175
|
prerelease: false
|
162
176
|
version_requirements: !ruby/object:Gem::Requirement
|
163
177
|
requirements:
|
164
|
-
- -
|
178
|
+
- - ">="
|
165
179
|
- !ruby/object:Gem::Version
|
166
|
-
version: 0
|
180
|
+
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: aws-s3
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
167
195
|
description: Snapshot creator for Digital Ocean droplets. Multi-threading inside.
|
168
196
|
Auto-cleanup feature. No matter how much droplets you have. Cron optimized.
|
169
197
|
email:
|
@@ -173,25 +201,17 @@ executables:
|
|
173
201
|
extensions: []
|
174
202
|
extra_rdoc_files: []
|
175
203
|
files:
|
176
|
-
- .gitignore
|
177
|
-
- .rubocop.yml
|
178
|
-
- .ruby-version
|
179
|
-
- .travis.yml
|
180
|
-
- Gemfile
|
181
|
-
- LICENSE.txt
|
182
204
|
- README.md
|
183
|
-
- Rakefile
|
184
205
|
- bin/do_snapshot
|
185
|
-
- do_snapshot.gemspec
|
186
206
|
- lib/do_snapshot.rb
|
187
207
|
- lib/do_snapshot/api.rb
|
188
208
|
- lib/do_snapshot/cli.rb
|
189
209
|
- lib/do_snapshot/command.rb
|
190
210
|
- lib/do_snapshot/core_ext/hash.rb
|
211
|
+
- lib/do_snapshot/distribution.rb
|
191
212
|
- lib/do_snapshot/log.rb
|
192
213
|
- lib/do_snapshot/mail.rb
|
193
214
|
- lib/do_snapshot/version.rb
|
194
|
-
- log/.keep
|
195
215
|
- spec/.keep
|
196
216
|
- spec/do_snapshot/api_spec.rb
|
197
217
|
- spec/do_snapshot/cli_spec.rb
|
@@ -209,8 +229,7 @@ files:
|
|
209
229
|
- spec/shared/environment.rb
|
210
230
|
- spec/shared/uri_helpers.rb
|
211
231
|
- spec/spec_helper.rb
|
212
|
-
|
213
|
-
homepage: http://github.com/merqlove/do_snapshot
|
232
|
+
homepage: http://dosnapshot.merqlove.ru/
|
214
233
|
licenses:
|
215
234
|
- MIT
|
216
235
|
metadata: {}
|
@@ -220,12 +239,12 @@ require_paths:
|
|
220
239
|
- lib
|
221
240
|
required_ruby_version: !ruby/object:Gem::Requirement
|
222
241
|
requirements:
|
223
|
-
- -
|
242
|
+
- - ">="
|
224
243
|
- !ruby/object:Gem::Version
|
225
244
|
version: '0'
|
226
245
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
227
246
|
requirements:
|
228
|
-
- -
|
247
|
+
- - ">="
|
229
248
|
- !ruby/object:Gem::Version
|
230
249
|
version: '0'
|
231
250
|
requirements: []
|
data/.gitignore
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
*.gem
|
2
|
-
*.rbc
|
3
|
-
.bundle
|
4
|
-
.config
|
5
|
-
.yardoc
|
6
|
-
Gemfile.lock
|
7
|
-
InstalledFiles
|
8
|
-
_yardoc
|
9
|
-
coverage
|
10
|
-
doc/
|
11
|
-
lib/bundler/man
|
12
|
-
pkg
|
13
|
-
rdoc
|
14
|
-
spec/reports
|
15
|
-
test/tmp
|
16
|
-
test/version_tmp
|
17
|
-
log/*
|
18
|
-
!log/.keep
|
19
|
-
tmp/*
|
20
|
-
!tmp/.keep
|
21
|
-
*.bundle
|
22
|
-
*.so
|
23
|
-
*.o
|
24
|
-
*.a
|
25
|
-
mkmf.log
|
26
|
-
.idea
|
27
|
-
.irb_history
|
28
|
-
.ruby-version
|
data/.rubocop.yml
DELETED
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
2.1.2
|
data/.travis.yml
DELETED
data/Gemfile
DELETED
data/LICENSE.txt
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
Copyright (c) 2014 Alexander Merkulov
|
2
|
-
|
3
|
-
MIT License
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
-
a copy of this software and associated documentation files (the
|
7
|
-
"Software"), to deal in the Software without restriction, including
|
8
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
-
permit persons to whom the Software is furnished to do so, subject to
|
11
|
-
the following conditions:
|
12
|
-
|
13
|
-
The above copyright notice and this permission notice shall be
|
14
|
-
included in all copies or substantial portions of the Software.
|
15
|
-
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
DELETED
data/do_snapshot.gemspec
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'do_snapshot/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = 'do_snapshot'
|
8
|
-
spec.version = DoSnapshot::VERSION
|
9
|
-
spec.authors = ['Alexander Merkulov']
|
10
|
-
spec.email = ['sasha@merqlove.ru']
|
11
|
-
spec.summary = 'Snapshot creator for Digital Ocean droplets. Multi-threading. Auto-cleanup. Cron optimized.'
|
12
|
-
spec.description = 'Snapshot creator for Digital Ocean droplets. Multi-threading inside. Auto-cleanup feature. No matter how much droplets you have. Cron optimized.'
|
13
|
-
spec.homepage = 'http://github.com/merqlove/do_snapshot'
|
14
|
-
spec.license = 'MIT'
|
15
|
-
|
16
|
-
spec.files = `git ls-files -z`.split("\x0")
|
17
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = ['lib']
|
20
|
-
|
21
|
-
spec.add_dependency 'digitalocean', '~> 1.2'
|
22
|
-
spec.add_dependency 'thor', '~> 0.19.1'
|
23
|
-
spec.add_dependency 'pony', '~> 1.1.0'
|
24
|
-
|
25
|
-
spec.add_development_dependency 'bundler', '~> 1.6'
|
26
|
-
spec.add_development_dependency 'rake'
|
27
|
-
spec.add_development_dependency 'rubocop'
|
28
|
-
spec.add_development_dependency 'rspec-core', '~> 3.0.2'
|
29
|
-
spec.add_development_dependency 'rspec-expectations', '~> 3.0.2'
|
30
|
-
spec.add_development_dependency 'rspec-mocks', '~> 3.0.2'
|
31
|
-
spec.add_development_dependency 'webmock', '~> 1.18.0'
|
32
|
-
spec.add_development_dependency 'coveralls', '~> 0.7.0'
|
33
|
-
end
|
data/log/.keep
DELETED
File without changes
|
data/tmp/.keep
DELETED
File without changes
|