do_snapshot 0.5.0 → 0.6.0
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 +4 -4
- data/README.md +20 -32
- data/lib/do_snapshot.rb +4 -0
- data/lib/do_snapshot/adapter.rb +22 -12
- data/lib/do_snapshot/command.rb +3 -4
- data/lib/do_snapshot/mail.rb +4 -2
- data/lib/do_snapshot/version.rb +1 -1
- data/spec/do_snapshot/adapter/abstract_spec.rb +1 -1
- data/spec/do_snapshot/adapter/digitalocean_v2_spec.rb +1 -1
- data/spec/do_snapshot/adapter_spec.rb +36 -0
- data/spec/do_snapshot/cli_spec.rb +2 -2
- data/spec/do_snapshot/command_spec.rb +1 -5
- data/spec/do_snapshot/log_spec.rb +12 -30
- data/spec/do_snapshot/mail_spec.rb +1 -1
- data/spec/do_snapshot/runner_spec.rb +1 -30
- data/spec/do_snapshot_spec.rb +1 -1
- data/spec/shared/api_helpers.rb +1 -1
- data/spec/shared/api_v2_helpers.rb +1 -1
- data/spec/shared/environment.rb +1 -1
- data/spec/shared/uri_helpers.rb +1 -1
- data/spec/spec_helper.rb +3 -1
- metadata +4 -23
- data/lib/do_snapshot/adapter/digitalocean.rb +0 -123
- data/spec/do_snapshot/adapter/digitalocean_spec.rb +0 -265
- data/spec/fixtures/digitalocean/v1/error_message.json +0 -4
- data/spec/fixtures/digitalocean/v1/response_event.json +0 -4
- data/spec/fixtures/digitalocean/v1/show_droplet.json +0 -39
- data/spec/fixtures/digitalocean/v1/show_droplet_inactive.json +0 -39
- data/spec/fixtures/digitalocean/v1/show_droplets.json +0 -35
- data/spec/fixtures/digitalocean/v1/show_droplets_empty.json +0 -4
- data/spec/fixtures/digitalocean/v1/show_event_done.json +0 -10
- data/spec/fixtures/digitalocean/v1/show_event_start.json +0 -10
- data/spec/shared/api_v1_helpers.rb +0 -97
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c7c9e3cd13d683e5ba91602e678fdcdb83cc434
|
4
|
+
data.tar.gz: e3dc35838e951eed9fdd6390203573af0de761a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bd1fd908c738b06b4ebb86d11f8e05f55c343d21eef81d769e103603d2e19f9462553ca9a7d0256df2d0ae0ce05fbd758ef3d20032aa277b35f891f3a9f512d2
|
7
|
+
data.tar.gz: e49489aaab514f945a3eb7f345c3c351545c3e099bbca988202796ebea2172cc32596b8472b87dfe201269892de7faaf6d2903adfc13de09beeb225f13559b84
|
data/README.md
CHANGED
@@ -12,18 +12,20 @@
|
|
12
12
|
|
13
13
|
Use this tool to backup DigitalOcean droplet's via snapshot method, on the fly!
|
14
14
|
|
15
|
-
##
|
15
|
+
## API Changes:
|
16
|
+
- 08.01.16: now we have to use DO API V2 only, because V1 is not work anymore.
|
17
|
+
- 17.10.15: now we use DO API V2 by default, due V1 deprecation at 11.2015.
|
16
18
|
|
17
|
-
Here some features:
|
19
|
+
Here are some features:
|
18
20
|
|
19
|
-
- Multiple threads out of the box
|
21
|
+
- Multiple threads out of the box, no matter how many droplets you have.
|
20
22
|
- Snapshots Auto-Cleanup.
|
21
|
-
- Auto-Boot Droplet
|
22
|
-
-
|
23
|
-
- Mail notifications when
|
23
|
+
- Auto-Boot Droplet if Snapshot Event fails or encounters a bad connection exception.
|
24
|
+
- Special binaries for cron and command-line, Homebrew, and standalone installers.
|
25
|
+
- Mail notifications when a snapshot fails or the maximum number of snapshots is reached for a droplet or droplets.
|
24
26
|
- Custom mail settings (You can set [Pony](https://github.com/benprew/pony) mail settings).
|
25
|
-
- Stop mode (
|
26
|
-
- Timeout option for long requests or uncaught loops.
|
27
|
+
- Stop mode (automatically stop creating new snapshots when the maximum is reached).
|
28
|
+
- Timeout option for long requests or uncaught loops. Defaults to 600 seconds, but can be changed.
|
27
29
|
- Logging into selected directory.
|
28
30
|
- Verbose mode for research.
|
29
31
|
- Quiet mode for silence.
|
@@ -34,16 +36,6 @@ Ruby versions 1.9.3 and higher. JRuby 1.7, 9.0.0.0 or later is also supported.
|
|
34
36
|
|
35
37
|
<img src="https://raw.githubusercontent.com/merqlove/do_snapshot/master/assets/example.png" style="max-width:100%" alt="DoSnaphot example">
|
36
38
|
|
37
|
-
### You can ask me, "Why you made this tool?"
|
38
|
-
|
39
|
-
- First. I needed stable tool, which can provide for me automatic Snapshot feature for all of my Droplets via Cron planner.
|
40
|
-
- I don't want to think how much snapshots for each droplet i have.
|
41
|
-
- I don't wont to sleep when my droplets Offline!!! And i wanted tool which can BOOT back droplets, which failed to snapshot.
|
42
|
-
- Also i want to understand what's going on if there some error. Mail is my choice. But logs also good.
|
43
|
-
- And ... sure ;) We want to do it fast as rocket! :)
|
44
|
-
- more more more...
|
45
|
-
- So this tool can save a lot of time for people.
|
46
|
-
|
47
39
|
## Installation
|
48
40
|
|
49
41
|
Install it yourself as:
|
@@ -91,26 +83,12 @@ You'll need to generate an access token in Digital Ocean's control panel at http
|
|
91
83
|
If you want to set keys without environment, than set it via options when you run do_snapshot:
|
92
84
|
|
93
85
|
$ do_snapshot --digital-ocean-access-token YOURLONGTOKEN
|
94
|
-
|
95
|
-
### Digitalocean API V1:
|
96
|
-
You'll need to generate an access token in Digital Ocean's control panel at https://cloud.digitalocean.com/api_access
|
97
|
-
|
98
|
-
$ export DIGITAL_OCEAN_CLIENT_ID="SOMEID"
|
99
|
-
$ export DIGITAL_OCEAN_API_KEY="SOMEKEY"
|
100
|
-
|
101
|
-
If you want to set keys without environment, than set it via options when you run do_snapshot:
|
102
|
-
|
103
|
-
$ do_snapshot --digital-ocean-client-id YOURLONGAPICLIENTID --digital-ocean-api-key YOURLONGAPIKEY
|
104
86
|
|
105
87
|
### How-To (Here is also [Longren Tutorial](https://longren.io/automate-making-snapshots-of-your-digitalocean-droplets/))
|
106
88
|
|
107
89
|
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.
|
108
90
|
|
109
91
|
$ do_snapshot --keep 5 -c
|
110
|
-
|
111
|
-
Using API V1:
|
112
|
-
|
113
|
-
$ do_snapshot -p 1
|
114
92
|
|
115
93
|
Keep latest 3 from selected droplet:
|
116
94
|
|
@@ -190,6 +168,16 @@ For working mailer you need to set e-mail settings via run options.
|
|
190
168
|
|
191
169
|
You can optionally specify parameters to select or exclude some droplets.
|
192
170
|
|
171
|
+
## You can ask, "Why you made this tool?"
|
172
|
+
|
173
|
+
- First. I needed stable tool, which can provide for me automatic Snapshot feature for all of my Droplets via Cron planner.
|
174
|
+
- I don't want to think how much snapshots for each droplet i have.
|
175
|
+
- I don't wont to sleep when my droplets Offline!!! And i wanted tool which can BOOT back droplets, which failed to snapshot.
|
176
|
+
- Also i want to understand what's going on if there some error. Mail is my choice. But logs also good.
|
177
|
+
- And ... sure ;) We want to do it fast as rocket! :)
|
178
|
+
- more more more...
|
179
|
+
- So this tool can save a lot of time for people.
|
180
|
+
|
193
181
|
## Donating:
|
194
182
|
Support this project and others by [merqlove](https://gratipay.com/~merqlove/) via [gratipay](https://gratipay.com/~merqlove/).
|
195
183
|
[](https://gratipay.com/merqlove/)
|
data/lib/do_snapshot.rb
CHANGED
@@ -41,6 +41,10 @@ module DoSnapshot
|
|
41
41
|
#
|
42
42
|
class NoTokenError < StandardError; end
|
43
43
|
|
44
|
+
# Protocol must exist.
|
45
|
+
#
|
46
|
+
class NoProtocolError < StandardError; end
|
47
|
+
|
44
48
|
# Base Exception for cases when we need id for log and/or something actions.
|
45
49
|
#
|
46
50
|
class RequestActionError < RequestError
|
data/lib/do_snapshot/adapter.rb
CHANGED
@@ -1,21 +1,31 @@
|
|
1
|
-
require_relative 'adapter/abstract'
|
2
|
-
|
3
|
-
require_relative 'adapter/digitalocean'
|
4
|
-
require_relative 'adapter/digitalocean_v2'
|
5
|
-
|
6
1
|
module DoSnapshot
|
7
2
|
# Adapter interface for API connections
|
8
3
|
# Ability to select DigitalOcean API versions.
|
9
4
|
#
|
10
5
|
module Adapter
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
6
|
+
autoload :Abstract, 'do_snapshot/adapter/abstract'
|
7
|
+
autoload :DigitaloceanV2, 'do_snapshot/adapter/digitalocean_v2'
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def api(protocol, options = {})
|
11
|
+
konst = find_protocol(protocol)
|
12
|
+
fail DoSnapshot::NoProtocolError, "Not existing protocol: #{protocol}." unless
|
13
|
+
DoSnapshot::Adapter.const_defined?(konst)
|
14
|
+
obj = DoSnapshot::Adapter.const_get(konst)
|
15
|
+
obj.new(options)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def find_protocol(protocol)
|
21
|
+
if protocol.is_a?(Integer)
|
22
|
+
"DigitaloceanV#{protocol}"
|
23
|
+
elsif protocol.is_a?(String)
|
24
|
+
protocol
|
25
|
+
else
|
26
|
+
'DigitaloceanV2'
|
27
|
+
end
|
17
28
|
end
|
18
29
|
end
|
19
|
-
module_function :api
|
20
30
|
end
|
21
31
|
end
|
data/lib/do_snapshot/command.rb
CHANGED
@@ -172,14 +172,13 @@ module DoSnapshot
|
|
172
172
|
|
173
173
|
return unless droplet
|
174
174
|
logger.info "Preparing droplet id: #{droplet.id} name: #{droplet.name} to take snapshot."
|
175
|
-
return if too_much_snapshots(droplet)
|
175
|
+
return if too_much_snapshots?(droplet)
|
176
176
|
processed_droplet_ids << droplet.id
|
177
177
|
thread_runner(droplet)
|
178
178
|
end
|
179
179
|
|
180
|
-
def too_much_snapshots(instance)
|
181
|
-
|
182
|
-
return false unless api.snapshots(instance).size >= keep
|
180
|
+
def too_much_snapshots?(instance)
|
181
|
+
return false if api.snapshots(instance).size < keep
|
183
182
|
warning_size(instance.id, instance.name, keep)
|
184
183
|
stop ? true : false
|
185
184
|
end
|
data/lib/do_snapshot/mail.rb
CHANGED
@@ -8,8 +8,6 @@ module DoSnapshot
|
|
8
8
|
# Shared mailer.
|
9
9
|
#
|
10
10
|
class Mail
|
11
|
-
include DoSnapshot::Helpers
|
12
|
-
|
13
11
|
attr_writer :mailer, :opts_default, :smtp_default
|
14
12
|
|
15
13
|
def initialize(options = {})
|
@@ -58,6 +56,10 @@ module DoSnapshot
|
|
58
56
|
|
59
57
|
protected
|
60
58
|
|
59
|
+
def logger
|
60
|
+
DoSnapshot::Helpers::UniversalLogger
|
61
|
+
end
|
62
|
+
|
61
63
|
def opts_default
|
62
64
|
@opts_default ||= {
|
63
65
|
subject: 'Digital Ocean: maximum snapshots is reached.',
|
data/lib/do_snapshot/version.rb
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
RSpec.describe DoSnapshot::Adapter do
|
5
|
+
include_context 'environment'
|
6
|
+
|
7
|
+
module DoSnapshot
|
8
|
+
module Adapter
|
9
|
+
class CustomAdapter # rubocop:disable Style/Documentation
|
10
|
+
def initialize(_ = {}); end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
subject(:adapter) { described_class }
|
16
|
+
|
17
|
+
describe '#api' do
|
18
|
+
it 'when adapter' do
|
19
|
+
api = adapter.api(2)
|
20
|
+
expect(api).to be_a_kind_of(DoSnapshot::Adapter::DigitaloceanV2)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'when custom adapter' do
|
24
|
+
api = adapter.api('CustomAdapter')
|
25
|
+
expect(api).to be_a_kind_of(DoSnapshot::Adapter::CustomAdapter)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'when wrong custom adapter' do
|
29
|
+
expect { adapter.api('CustomAdapter2') }.to raise_exception(DoSnapshot::NoProtocolError)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'when error' do
|
33
|
+
expect { adapter.api(1) }.to raise_exception(DoSnapshot::NoProtocolError)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -2,11 +2,11 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
4
|
RSpec.describe DoSnapshot::CLI do
|
5
|
-
include_context '
|
5
|
+
include_context 'environment'
|
6
6
|
include_context 'api_v2_helpers'
|
7
7
|
|
8
8
|
subject(:cli) { described_class }
|
9
|
-
subject(:api) { DoSnapshot::Adapter::
|
9
|
+
subject(:api) { DoSnapshot::Adapter::DigitaloceanV2 }
|
10
10
|
|
11
11
|
describe '.initialize' do
|
12
12
|
it 'with args & options' do
|
@@ -2,16 +2,12 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
4
|
RSpec.describe DoSnapshot::Command do
|
5
|
-
include_context '
|
5
|
+
include_context 'environment'
|
6
6
|
include_context 'uri_helpers'
|
7
7
|
|
8
8
|
subject(:cmd) { DoSnapshot::Command.new }
|
9
9
|
subject(:log) { DoSnapshot::Log }
|
10
10
|
|
11
|
-
describe 'V1' do
|
12
|
-
include_context 'api_v1_helpers'
|
13
|
-
end
|
14
|
-
|
15
11
|
describe 'V2' do
|
16
12
|
include_context 'api_v2_helpers'
|
17
13
|
|
@@ -2,40 +2,16 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
4
|
RSpec.describe DoSnapshot::Log do
|
5
|
-
include_context '
|
5
|
+
include_context 'environment'
|
6
6
|
|
7
7
|
subject(:log) { described_class }
|
8
8
|
|
9
9
|
describe 'will have message' do
|
10
|
-
it
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
it '#debug' do
|
17
|
-
expect(DoSnapshot.logger).to respond_to(:debug)
|
18
|
-
DoSnapshot.logger.info('fff')
|
19
|
-
expect(DoSnapshot.logger.buffer).to include('fff')
|
20
|
-
end
|
21
|
-
|
22
|
-
it '#warn' do
|
23
|
-
expect(DoSnapshot.logger).to respond_to(:warn)
|
24
|
-
DoSnapshot.logger.info('fff')
|
25
|
-
expect(DoSnapshot.logger.buffer).to include('fff')
|
26
|
-
end
|
27
|
-
|
28
|
-
it '#fatal' do
|
29
|
-
expect(DoSnapshot.logger).to respond_to(:fatal)
|
30
|
-
DoSnapshot.logger.info('fff')
|
31
|
-
expect(DoSnapshot.logger.buffer).to include('fff')
|
32
|
-
end
|
33
|
-
|
34
|
-
it '#error' do
|
35
|
-
expect(DoSnapshot.logger).to respond_to(:error)
|
36
|
-
DoSnapshot.logger.info('fff')
|
37
|
-
expect(DoSnapshot.logger.buffer).to include('fff')
|
38
|
-
end
|
10
|
+
it('#info') { logger_respond_to(:info) }
|
11
|
+
it('#debug') { logger_respond_to(:debug) }
|
12
|
+
it('#warn') { logger_respond_to(:warn) }
|
13
|
+
it('#fatal') { logger_respond_to(:fatal) }
|
14
|
+
it('#error') { logger_respond_to(:error) }
|
39
15
|
|
40
16
|
it '#blablabla' do
|
41
17
|
expect(DoSnapshot.logger).not_to respond_to(:blablabla)
|
@@ -49,6 +25,12 @@ RSpec.describe DoSnapshot::Log do
|
|
49
25
|
end
|
50
26
|
DoSnapshot.logger = DoSnapshot::Log.new
|
51
27
|
end
|
28
|
+
|
29
|
+
def logger_respond_to(type)
|
30
|
+
expect(DoSnapshot.logger).to respond_to(type)
|
31
|
+
DoSnapshot.logger.send(type, 'fff')
|
32
|
+
expect(DoSnapshot.logger.buffer).to include('fff')
|
33
|
+
end
|
52
34
|
end
|
53
35
|
|
54
36
|
describe 'will work with files' do
|
@@ -2,7 +2,7 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
4
|
RSpec.describe DoSnapshot::Runner, type: :aruba do
|
5
|
-
include_context '
|
5
|
+
include_context 'environment'
|
6
6
|
|
7
7
|
context 'commands' do
|
8
8
|
context '.snap' do
|
@@ -211,35 +211,6 @@ RSpec.describe DoSnapshot::Runner, type: :aruba do
|
|
211
211
|
end
|
212
212
|
end
|
213
213
|
|
214
|
-
context 'API V1' do
|
215
|
-
let(:default_options_cli) { default_options.merge(protocol: 1) }
|
216
|
-
let(:snapshot_name) { "foo_#{DateTime.now.strftime('%Y_%m_%d')}" }
|
217
|
-
|
218
|
-
include_context 'api_v1_helpers'
|
219
|
-
it_behaves_like '.snap methods'
|
220
|
-
|
221
|
-
context 'when no credentials' do
|
222
|
-
it 'with warning about digitalocean credentials' do
|
223
|
-
with_environment(cli_env_nil) do
|
224
|
-
run "do_snapshot snap #{options_line}"
|
225
|
-
|
226
|
-
expect(last_command).to have_exit_status(1)
|
227
|
-
expect(all_stdout)
|
228
|
-
.to include(t_wrong_keys(%w( digital_ocean_client_id digital_ocean_api_key ).join(', ')))
|
229
|
-
end
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
context 'when different credentials' do
|
234
|
-
let(:keys_uri) { "api_key=#{cli_keys_other[:digital_ocean_api_key]}&client_id=#{cli_keys_other[:digital_ocean_client_id]}" }
|
235
|
-
|
236
|
-
it 'with no warning' do
|
237
|
-
hash_attribute_eq(cli_keys_other)
|
238
|
-
|
239
|
-
expect(last_command).to have_exit_status(0)
|
240
|
-
end
|
241
|
-
end
|
242
|
-
end
|
243
214
|
end
|
244
215
|
|
245
216
|
context '.help' do
|
data/spec/do_snapshot_spec.rb
CHANGED
data/spec/shared/api_helpers.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
|
-
shared_context 'api_v2_helpers' do
|
4
|
+
RSpec.shared_context 'api_v2_helpers' do
|
5
5
|
let(:api_base) { 'https://api.digitalocean.com/v2' }
|
6
6
|
let(:droplets_api_base) { "#{api_base}/droplets" }
|
7
7
|
let(:api_access_token) { "Bearer #{access_token}" }
|
data/spec/shared/environment.rb
CHANGED
data/spec/shared/uri_helpers.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
|
-
shared_context 'uri_helpers' do
|
4
|
+
RSpec.shared_context 'uri_helpers' do
|
5
5
|
let(:droplet_url) { url_with_id(droplet_find_uri, droplet_id) }
|
6
6
|
let(:droplet_stop_url) { url_with_id(droplet_stop_uri, droplet_id) }
|
7
7
|
let(:droplet_start_url) { url_with_id(droplet_start_uri, droplet_id) }
|
data/spec/spec_helper.rb
CHANGED
@@ -4,12 +4,14 @@ Coveralls.wear! do
|
|
4
4
|
add_filter '/spec/*'
|
5
5
|
end
|
6
6
|
|
7
|
+
require 'bundler'
|
8
|
+
Bundler.setup
|
9
|
+
|
7
10
|
require 'do_snapshot/cli'
|
8
11
|
require 'webmock/rspec'
|
9
12
|
require 'fileutils'
|
10
13
|
require 'digitalocean_c'
|
11
14
|
require_relative 'shared/api_helpers'
|
12
|
-
require_relative 'shared/api_v1_helpers'
|
13
15
|
require_relative 'shared/api_v2_helpers'
|
14
16
|
require_relative 'shared/uri_helpers'
|
15
17
|
require_relative 'shared/environment'
|
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.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexander Merkulov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: digitalocean_c
|
@@ -80,7 +80,6 @@ files:
|
|
80
80
|
- lib/do_snapshot.rb
|
81
81
|
- lib/do_snapshot/adapter.rb
|
82
82
|
- lib/do_snapshot/adapter/abstract.rb
|
83
|
-
- lib/do_snapshot/adapter/digitalocean.rb
|
84
83
|
- lib/do_snapshot/adapter/digitalocean_v2.rb
|
85
84
|
- lib/do_snapshot/cli.rb
|
86
85
|
- lib/do_snapshot/command.rb
|
@@ -94,8 +93,8 @@ files:
|
|
94
93
|
- lib/do_snapshot/version.rb
|
95
94
|
- spec/.keep
|
96
95
|
- spec/do_snapshot/adapter/abstract_spec.rb
|
97
|
-
- spec/do_snapshot/adapter/digitalocean_spec.rb
|
98
96
|
- spec/do_snapshot/adapter/digitalocean_v2_spec.rb
|
97
|
+
- spec/do_snapshot/adapter_spec.rb
|
99
98
|
- spec/do_snapshot/cli_spec.rb
|
100
99
|
- spec/do_snapshot/command_spec.rb
|
101
100
|
- spec/do_snapshot/configuration_spec.rb
|
@@ -103,14 +102,6 @@ files:
|
|
103
102
|
- spec/do_snapshot/mail_spec.rb
|
104
103
|
- spec/do_snapshot/runner_spec.rb
|
105
104
|
- spec/do_snapshot_spec.rb
|
106
|
-
- spec/fixtures/digitalocean/v1/error_message.json
|
107
|
-
- spec/fixtures/digitalocean/v1/response_event.json
|
108
|
-
- spec/fixtures/digitalocean/v1/show_droplet.json
|
109
|
-
- spec/fixtures/digitalocean/v1/show_droplet_inactive.json
|
110
|
-
- spec/fixtures/digitalocean/v1/show_droplets.json
|
111
|
-
- spec/fixtures/digitalocean/v1/show_droplets_empty.json
|
112
|
-
- spec/fixtures/digitalocean/v1/show_event_done.json
|
113
|
-
- spec/fixtures/digitalocean/v1/show_event_start.json
|
114
105
|
- spec/fixtures/digitalocean/v2/empty.json
|
115
106
|
- spec/fixtures/digitalocean/v2/error_message.json
|
116
107
|
- spec/fixtures/digitalocean/v2/response_event.json
|
@@ -125,7 +116,6 @@ files:
|
|
125
116
|
- spec/fixtures/digitalocean/v2/show_event_power_on_start.json
|
126
117
|
- spec/fixtures/digitalocean/v2/show_event_start.json
|
127
118
|
- spec/shared/api_helpers.rb
|
128
|
-
- spec/shared/api_v1_helpers.rb
|
129
119
|
- spec/shared/api_v2_helpers.rb
|
130
120
|
- spec/shared/environment.rb
|
131
121
|
- spec/shared/uri_helpers.rb
|
@@ -160,8 +150,8 @@ summary: A command-line snapshot maker for your DigitalOcean droplets. Fully Aut
|
|
160
150
|
test_files:
|
161
151
|
- spec/.keep
|
162
152
|
- spec/do_snapshot/adapter/abstract_spec.rb
|
163
|
-
- spec/do_snapshot/adapter/digitalocean_spec.rb
|
164
153
|
- spec/do_snapshot/adapter/digitalocean_v2_spec.rb
|
154
|
+
- spec/do_snapshot/adapter_spec.rb
|
165
155
|
- spec/do_snapshot/cli_spec.rb
|
166
156
|
- spec/do_snapshot/command_spec.rb
|
167
157
|
- spec/do_snapshot/configuration_spec.rb
|
@@ -169,14 +159,6 @@ test_files:
|
|
169
159
|
- spec/do_snapshot/mail_spec.rb
|
170
160
|
- spec/do_snapshot/runner_spec.rb
|
171
161
|
- spec/do_snapshot_spec.rb
|
172
|
-
- spec/fixtures/digitalocean/v1/error_message.json
|
173
|
-
- spec/fixtures/digitalocean/v1/response_event.json
|
174
|
-
- spec/fixtures/digitalocean/v1/show_droplet.json
|
175
|
-
- spec/fixtures/digitalocean/v1/show_droplet_inactive.json
|
176
|
-
- spec/fixtures/digitalocean/v1/show_droplets.json
|
177
|
-
- spec/fixtures/digitalocean/v1/show_droplets_empty.json
|
178
|
-
- spec/fixtures/digitalocean/v1/show_event_done.json
|
179
|
-
- spec/fixtures/digitalocean/v1/show_event_start.json
|
180
162
|
- spec/fixtures/digitalocean/v2/empty.json
|
181
163
|
- spec/fixtures/digitalocean/v2/error_message.json
|
182
164
|
- spec/fixtures/digitalocean/v2/response_event.json
|
@@ -191,7 +173,6 @@ test_files:
|
|
191
173
|
- spec/fixtures/digitalocean/v2/show_event_power_on_start.json
|
192
174
|
- spec/fixtures/digitalocean/v2/show_event_start.json
|
193
175
|
- spec/shared/api_helpers.rb
|
194
|
-
- spec/shared/api_v1_helpers.rb
|
195
176
|
- spec/shared/api_v2_helpers.rb
|
196
177
|
- spec/shared/environment.rb
|
197
178
|
- spec/shared/uri_helpers.rb
|
@@ -1,123 +0,0 @@
|
|
1
|
-
# -*- encoding : utf-8 -*-
|
2
|
-
require 'digitalocean_c' unless defined?(::DigitaloceanC)
|
3
|
-
|
4
|
-
module DoSnapshot
|
5
|
-
module Adapter
|
6
|
-
# API for CLI commands
|
7
|
-
# Operating with Digital Ocean.
|
8
|
-
#
|
9
|
-
class Digitalocean < Abstract
|
10
|
-
# Get single droplet from DigitalOcean
|
11
|
-
#
|
12
|
-
def droplet(id)
|
13
|
-
# noinspection RubyResolve
|
14
|
-
response = ::DigitaloceanC::Droplet.find(id)
|
15
|
-
fail DropletFindError.new(id), response.message unless response.status.include? 'OK'
|
16
|
-
response.droplet
|
17
|
-
end
|
18
|
-
|
19
|
-
# Get droplets list from DigitalOcean
|
20
|
-
#
|
21
|
-
def droplets
|
22
|
-
# noinspection RubyResolve
|
23
|
-
response = ::DigitaloceanC::Droplet.all
|
24
|
-
fail DropletListError, response.message unless response.status.include? 'OK'
|
25
|
-
response.droplets
|
26
|
-
end
|
27
|
-
|
28
|
-
def snapshots(instance)
|
29
|
-
instance.snapshots
|
30
|
-
end
|
31
|
-
|
32
|
-
# Request Power On for droplet
|
33
|
-
#
|
34
|
-
def power_on(id)
|
35
|
-
# noinspection RubyResolve
|
36
|
-
event = ::DigitaloceanC::Droplet.power_on(id)
|
37
|
-
case event && event.status
|
38
|
-
when 'OK'
|
39
|
-
logger.info "Droplet id: #{id} is requested for Power On."
|
40
|
-
else
|
41
|
-
logger.error "Droplet id: #{id} is failed to request for Power On."
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
# Power Off request for Droplet
|
46
|
-
#
|
47
|
-
def stop_droplet(id)
|
48
|
-
# noinspection RubyResolve,RubyResolve
|
49
|
-
event = ::DigitaloceanC::Droplet.power_off(id)
|
50
|
-
|
51
|
-
fail event.message unless event.status.include? 'OK'
|
52
|
-
|
53
|
-
# noinspection RubyResolve
|
54
|
-
wait_shutdown(id, event.event_id)
|
55
|
-
rescue => e
|
56
|
-
raise DropletShutdownError.new(id), e.message, e.backtrace
|
57
|
-
end
|
58
|
-
|
59
|
-
# Sending event to create snapshot via DigitalOcean API and wait for success
|
60
|
-
#
|
61
|
-
def create_snapshot(id, name)
|
62
|
-
# noinspection RubyResolve,RubyResolve
|
63
|
-
event = ::DigitaloceanC::Droplet.snapshot(id, name: name)
|
64
|
-
|
65
|
-
if !event
|
66
|
-
fail DoSnapshot::SnapshotCreateError.new(id), 'Something wrong with DigitalOcean or with your connection :)'
|
67
|
-
elsif event && !event.status.include?('OK')
|
68
|
-
fail DoSnapshot::SnapshotCreateError.new(id), event.message
|
69
|
-
end
|
70
|
-
|
71
|
-
# noinspection RubyResolve
|
72
|
-
wait_event(event.event_id)
|
73
|
-
end
|
74
|
-
|
75
|
-
# Checking if droplet is powered off.
|
76
|
-
#
|
77
|
-
def inactive?(id)
|
78
|
-
instance = droplet(id)
|
79
|
-
|
80
|
-
instance.status.include?('off')
|
81
|
-
end
|
82
|
-
|
83
|
-
# Cleanup our snapshots.
|
84
|
-
#
|
85
|
-
def cleanup_snapshots(instance, size)
|
86
|
-
(0..size).each do |i|
|
87
|
-
# noinspection RubyResolve
|
88
|
-
snapshot = instance.snapshots[i]
|
89
|
-
event = ::DigitaloceanC::Image.destroy(snapshot.id)
|
90
|
-
|
91
|
-
after_cleanup(instance.id, instance.name, snapshot, event)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def check_keys
|
96
|
-
logger.debug 'Checking DigitalOcean Id\'s.'
|
97
|
-
errors = %w( DIGITAL_OCEAN_CLIENT_ID DIGITAL_OCEAN_API_KEY ).map { |key| key if ENV[key].blank? }.compact
|
98
|
-
fail DoSnapshot::NoKeysError, "You must have #{errors.join(', ')} in environment or set it via options." if errors.size > 0
|
99
|
-
end
|
100
|
-
|
101
|
-
protected
|
102
|
-
|
103
|
-
# Set id's of Digital Ocean API.
|
104
|
-
#
|
105
|
-
def set_id
|
106
|
-
logger.debug 'Setting DigitalOcean Id\'s.'
|
107
|
-
::DigitaloceanC.client_id = ENV['DIGITAL_OCEAN_CLIENT_ID']
|
108
|
-
::DigitaloceanC.api_key = ENV['DIGITAL_OCEAN_API_KEY']
|
109
|
-
end
|
110
|
-
|
111
|
-
# Looking for event status.
|
112
|
-
#
|
113
|
-
def get_event_status(id, time)
|
114
|
-
return true if timeout?(id, time)
|
115
|
-
|
116
|
-
event = ::DigitaloceanC::Event.find(id)
|
117
|
-
fail DoSnapshot::EventError.new(id), event.message unless event.status.include?('OK')
|
118
|
-
# noinspection RubyResolve,RubyResolve
|
119
|
-
event.event.percentage && event.event.percentage.include?('100') ? true : false
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
@@ -1,265 +0,0 @@
|
|
1
|
-
# -*- encoding : utf-8 -*-
|
2
|
-
require 'spec_helper'
|
3
|
-
|
4
|
-
RSpec.describe DoSnapshot::Adapter::Digitalocean do
|
5
|
-
include_context 'spec'
|
6
|
-
include_context 'api_v1_helpers'
|
7
|
-
|
8
|
-
subject(:api) { described_class }
|
9
|
-
subject(:log) { DoSnapshot::Log }
|
10
|
-
|
11
|
-
describe '.initialize' do
|
12
|
-
describe '#delay' do
|
13
|
-
let(:delay) { 5 }
|
14
|
-
let(:instance) { api.new(delay: delay) }
|
15
|
-
it('with custom delay') { expect(instance.delay).to eq delay }
|
16
|
-
end
|
17
|
-
|
18
|
-
describe '#timeout' do
|
19
|
-
let(:timeout) { 5 }
|
20
|
-
let(:instance) { api.new(timeout: timeout) }
|
21
|
-
it('with custom timeout') { expect(instance.timeout).to eq timeout }
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
describe 'droplets' do
|
26
|
-
let(:instance) { api.new(delay: delay, timeout: timeout) }
|
27
|
-
include_context 'uri_helpers'
|
28
|
-
|
29
|
-
describe '.droplet' do
|
30
|
-
it 'with droplet' do
|
31
|
-
stub_droplet(droplet_id)
|
32
|
-
|
33
|
-
instance.droplet(droplet_id)
|
34
|
-
|
35
|
-
expect(a_request(:get, droplet_url))
|
36
|
-
.to have_been_made
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'with error' do
|
40
|
-
stub_droplet_fail(droplet_id)
|
41
|
-
|
42
|
-
expect { instance.droplet(droplet_id) }
|
43
|
-
.to raise_error(DoSnapshot::DropletFindError)
|
44
|
-
expect(DoSnapshot.logger.buffer)
|
45
|
-
.to include "Droplet id: #{droplet_id} Not Found"
|
46
|
-
|
47
|
-
expect(a_request(:get, droplet_url))
|
48
|
-
.to have_been_made
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
describe '.droplets' do
|
53
|
-
it 'with droplets' do
|
54
|
-
stub_droplets
|
55
|
-
|
56
|
-
instance.droplets
|
57
|
-
|
58
|
-
expect(a_request(:get, droplets_uri))
|
59
|
-
.to have_been_made
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'with error' do
|
63
|
-
stub_droplets_fail
|
64
|
-
|
65
|
-
expect { instance.droplets }.to raise_error(DoSnapshot::DropletListError)
|
66
|
-
expect(DoSnapshot.logger.buffer)
|
67
|
-
.to include 'Droplet Listing is failed to retrieve'
|
68
|
-
|
69
|
-
expect(a_request(:get, droplets_uri))
|
70
|
-
.to have_been_made
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
describe '.start_droplet' do
|
75
|
-
it 'with event' do
|
76
|
-
stub_droplet_inactive(droplet_id)
|
77
|
-
stub_droplet_start(droplet_id)
|
78
|
-
|
79
|
-
instance.start_droplet(droplet_id)
|
80
|
-
expect(DoSnapshot.logger.buffer).to include "Droplet id: #{droplet_id} is requested for Power On."
|
81
|
-
|
82
|
-
expect(a_request(:get, droplet_start_url))
|
83
|
-
.to have_been_made
|
84
|
-
expect(a_request(:get, droplet_url))
|
85
|
-
.to have_been_made
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'with warning message' do
|
89
|
-
stub_droplet(droplet_id)
|
90
|
-
|
91
|
-
expect { instance.start_droplet(droplet_id) }
|
92
|
-
.not_to raise_error
|
93
|
-
expect(DoSnapshot.logger.buffer)
|
94
|
-
.to include "Droplet #{droplet_id} is still running. Skipping."
|
95
|
-
|
96
|
-
expect(a_request(:get, droplet_url))
|
97
|
-
.to have_been_made
|
98
|
-
end
|
99
|
-
|
100
|
-
it 'with error' do
|
101
|
-
stub_droplet_fail(droplet_id)
|
102
|
-
|
103
|
-
expect { instance.start_droplet(droplet_id) }
|
104
|
-
.to raise_error(DoSnapshot::DropletFindError)
|
105
|
-
|
106
|
-
expect(a_request(:get, droplet_url))
|
107
|
-
.to have_been_made
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
describe '.stop_droplet by power status' do
|
112
|
-
let(:instance) { api.new(delay: delay, timeout: timeout, stop_by: :power_status) }
|
113
|
-
|
114
|
-
it 'with success' do
|
115
|
-
stub_event_done(event_id)
|
116
|
-
stub_droplet_stop(droplet_id)
|
117
|
-
stub_droplet_inactive(droplet_id)
|
118
|
-
|
119
|
-
instance.stop_droplet(droplet_id)
|
120
|
-
|
121
|
-
expect(a_request(:get, droplet_stop_url))
|
122
|
-
.to have_been_made
|
123
|
-
expect(a_request(:get, droplet_url))
|
124
|
-
.to have_been_made
|
125
|
-
end
|
126
|
-
|
127
|
-
it 'with error' do
|
128
|
-
stub_droplet_stop_fail(droplet_id)
|
129
|
-
stub_droplet(droplet_id)
|
130
|
-
|
131
|
-
instance.timeout = 1
|
132
|
-
expect { instance.stop_droplet(droplet_id) }
|
133
|
-
.to raise_error(DoSnapshot::DropletShutdownError)
|
134
|
-
instance.timeout = timeout
|
135
|
-
expect(DoSnapshot.logger.buffer)
|
136
|
-
.to include 'Droplet id: 100823 is Failed to Power Off.'
|
137
|
-
|
138
|
-
expect(a_request(:get, droplet_stop_url))
|
139
|
-
.to have_been_made
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
describe '.stop_droplet by event' do
|
144
|
-
it 'with success' do
|
145
|
-
stub_event_done(event_id)
|
146
|
-
stub_droplet_stop(droplet_id)
|
147
|
-
|
148
|
-
instance.stop_droplet(droplet_id)
|
149
|
-
|
150
|
-
expect(a_request(:get, droplet_stop_url))
|
151
|
-
.to have_been_made
|
152
|
-
expect(a_request(:get, event_find_url))
|
153
|
-
.to have_been_made
|
154
|
-
end
|
155
|
-
|
156
|
-
it 'with error' do
|
157
|
-
stub_droplet_stop_fail(droplet_id)
|
158
|
-
|
159
|
-
expect { instance.stop_droplet(droplet_id) }
|
160
|
-
.to raise_error(DoSnapshot::DropletShutdownError)
|
161
|
-
expect(DoSnapshot.logger.buffer)
|
162
|
-
.to include 'Droplet id: 100823 is Failed to Power Off.'
|
163
|
-
|
164
|
-
expect(a_request(:get, droplet_stop_url))
|
165
|
-
.to have_been_made
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
describe '.create_snapshot' do
|
170
|
-
it 'with success' do
|
171
|
-
stub_event_done(event_id)
|
172
|
-
stub_droplet_snapshot(droplet_id, snapshot_name)
|
173
|
-
|
174
|
-
expect { instance.create_snapshot(droplet_id, snapshot_name) }
|
175
|
-
.not_to raise_error
|
176
|
-
|
177
|
-
expect(a_request(:get, droplet_snapshot_url))
|
178
|
-
.to have_been_made
|
179
|
-
expect(a_request(:get, event_find_url))
|
180
|
-
.to have_been_made
|
181
|
-
end
|
182
|
-
|
183
|
-
it 'with error' do
|
184
|
-
stub_droplet_snapshot_fail(droplet_id, snapshot_name)
|
185
|
-
|
186
|
-
expect { instance.create_snapshot(droplet_id, snapshot_name) }
|
187
|
-
.to raise_error(DoSnapshot::SnapshotCreateError)
|
188
|
-
|
189
|
-
expect(a_request(:get, droplet_snapshot_url))
|
190
|
-
.to have_been_made
|
191
|
-
end
|
192
|
-
|
193
|
-
it 'with event error' do
|
194
|
-
stub_droplet_snapshot(droplet_id, snapshot_name)
|
195
|
-
stub_event_fail(event_id)
|
196
|
-
|
197
|
-
expect { instance.create_snapshot(droplet_id, snapshot_name) }
|
198
|
-
.not_to raise_error
|
199
|
-
expect(DoSnapshot.logger.buffer)
|
200
|
-
.to include "Event id: #{event_id} is failed!"
|
201
|
-
|
202
|
-
expect(a_request(:get, droplet_snapshot_url))
|
203
|
-
.to have_been_made
|
204
|
-
expect(a_request(:get, event_find_url))
|
205
|
-
.to have_been_made
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
describe '.inactive?' do
|
210
|
-
it 'when inactive' do
|
211
|
-
stub_droplet_inactive(droplet_id)
|
212
|
-
|
213
|
-
expect(instance.inactive?(droplet_id))
|
214
|
-
.to be_truthy
|
215
|
-
end
|
216
|
-
|
217
|
-
it 'when active' do
|
218
|
-
stub_droplet(droplet_id)
|
219
|
-
|
220
|
-
expect(instance.inactive?(droplet_id))
|
221
|
-
.to be_falsey
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
describe '.cleanup_snapshots' do
|
226
|
-
it 'with success' do
|
227
|
-
stub_droplet(droplet_id)
|
228
|
-
stub_image_destroy(image_id)
|
229
|
-
stub_image_destroy(image_id2)
|
230
|
-
|
231
|
-
droplet = instance.droplet(droplet_id)
|
232
|
-
expect { instance.cleanup_snapshots(droplet, 1) }
|
233
|
-
.not_to raise_error
|
234
|
-
expect(DoSnapshot.logger.buffer)
|
235
|
-
.to include 'Snapshot name: mrcr.ru_2014_07_19 delete requested.'
|
236
|
-
|
237
|
-
expect(a_request(:get, droplet_url))
|
238
|
-
.to have_been_made
|
239
|
-
expect(a_request(:get, image_destroy_url))
|
240
|
-
.to have_been_made
|
241
|
-
expect(a_request(:get, image_destroy2_url))
|
242
|
-
.to have_been_made
|
243
|
-
end
|
244
|
-
|
245
|
-
it 'with warning message' do
|
246
|
-
stub_droplet(droplet_id)
|
247
|
-
stub_image_destroy_fail(image_id)
|
248
|
-
stub_image_destroy_fail(image_id2)
|
249
|
-
|
250
|
-
droplet = instance.droplet(droplet_id)
|
251
|
-
expect { instance.cleanup_snapshots(droplet, 1) }
|
252
|
-
.not_to raise_error
|
253
|
-
expect(DoSnapshot.logger.buffer)
|
254
|
-
.to include 'Some Message'
|
255
|
-
|
256
|
-
expect(a_request(:get, droplet_url))
|
257
|
-
.to have_been_made
|
258
|
-
expect(a_request(:get, image_destroy_url))
|
259
|
-
.to have_been_made
|
260
|
-
expect(a_request(:get, image_destroy2_url))
|
261
|
-
.to have_been_made
|
262
|
-
end
|
263
|
-
end
|
264
|
-
end
|
265
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"status": "OK",
|
3
|
-
"droplet": {
|
4
|
-
"backups_active": null,
|
5
|
-
"id": 100823,
|
6
|
-
"image_id": 420,
|
7
|
-
"name": "foo",
|
8
|
-
"ip_address": "33.33.33.10",
|
9
|
-
"snapshots": [
|
10
|
-
{
|
11
|
-
"id": 5019770,
|
12
|
-
"name": "mrcr.ru_2014_07_19",
|
13
|
-
"slug": null,
|
14
|
-
"distribution": "CentOS"
|
15
|
-
},
|
16
|
-
{
|
17
|
-
"id": 5019903,
|
18
|
-
"name": "mrcr.ru_2014_07_19",
|
19
|
-
"slug": null,
|
20
|
-
"distribution": "CentOS"
|
21
|
-
},
|
22
|
-
{
|
23
|
-
"id": 5020783,
|
24
|
-
"name": "mrcr.ru_2014_07_19",
|
25
|
-
"slug": null,
|
26
|
-
"distribution": "CentOS"
|
27
|
-
},
|
28
|
-
{
|
29
|
-
"id": 5030783,
|
30
|
-
"name": "mrcr.ru_2014_07_19",
|
31
|
-
"slug": null,
|
32
|
-
"distribution": "CentOS"
|
33
|
-
}
|
34
|
-
],
|
35
|
-
"region_id": 1,
|
36
|
-
"size_id": 33,
|
37
|
-
"status": "active"
|
38
|
-
}
|
39
|
-
}
|
@@ -1,39 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"status": "OK",
|
3
|
-
"droplet": {
|
4
|
-
"backups_active": null,
|
5
|
-
"id": 100823,
|
6
|
-
"image_id": 420,
|
7
|
-
"name": "foo",
|
8
|
-
"ip_address": "33.33.33.10",
|
9
|
-
"snapshots": [
|
10
|
-
{
|
11
|
-
"id": 5019770,
|
12
|
-
"name": "mrcr.ru_2014_07_19",
|
13
|
-
"slug": null,
|
14
|
-
"distribution": "CentOS"
|
15
|
-
},
|
16
|
-
{
|
17
|
-
"id": 5019903,
|
18
|
-
"name": "mrcr.ru_2014_07_19",
|
19
|
-
"slug": null,
|
20
|
-
"distribution": "CentOS"
|
21
|
-
},
|
22
|
-
{
|
23
|
-
"id": 5020783,
|
24
|
-
"name": "mrcr.ru_2014_07_19",
|
25
|
-
"slug": null,
|
26
|
-
"distribution": "CentOS"
|
27
|
-
},
|
28
|
-
{
|
29
|
-
"id": 5030783,
|
30
|
-
"name": "mrcr.ru_2014_07_19",
|
31
|
-
"slug": null,
|
32
|
-
"distribution": "CentOS"
|
33
|
-
}
|
34
|
-
],
|
35
|
-
"region_id": 1,
|
36
|
-
"size_id": 33,
|
37
|
-
"status": "off"
|
38
|
-
}
|
39
|
-
}
|
@@ -1,35 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"status": "OK",
|
3
|
-
"droplets": [
|
4
|
-
{
|
5
|
-
"ip_address": "33.33.33.10",
|
6
|
-
"backups_active": null,
|
7
|
-
"id": 100823,
|
8
|
-
"image_id": 420,
|
9
|
-
"name": "test222",
|
10
|
-
"region_id": 1,
|
11
|
-
"size_id": 33,
|
12
|
-
"status": "active"
|
13
|
-
},
|
14
|
-
{
|
15
|
-
"ip_address": "33.33.33.10",
|
16
|
-
"backups_active": null,
|
17
|
-
"id": 100824,
|
18
|
-
"image_id": 420,
|
19
|
-
"name": "test223",
|
20
|
-
"region_id": 1,
|
21
|
-
"size_id": 33,
|
22
|
-
"status": "active"
|
23
|
-
},
|
24
|
-
{
|
25
|
-
"ip_address": "33.33.33.10",
|
26
|
-
"backups_active": null,
|
27
|
-
"id": 100825,
|
28
|
-
"image_id": 420,
|
29
|
-
"name": "foo",
|
30
|
-
"region_id": 1,
|
31
|
-
"size_id": 33,
|
32
|
-
"status": "active"
|
33
|
-
}
|
34
|
-
]
|
35
|
-
}
|
@@ -1,97 +0,0 @@
|
|
1
|
-
# -*- encoding : utf-8 -*-
|
2
|
-
require 'spec_helper'
|
3
|
-
|
4
|
-
shared_context 'api_v1_helpers' do
|
5
|
-
let(:api_base) { 'https://api.digitalocean.com/v1' }
|
6
|
-
let(:keys_uri) { "api_key=#{api_key}&client_id=#{client_key}" }
|
7
|
-
let(:droplets_api_base) { "#{api_base}/droplets" }
|
8
|
-
let(:events_api_base) { "#{api_base}/events" }
|
9
|
-
let(:images_api_base) { "#{api_base}/images" }
|
10
|
-
let(:image_destroy_uri) { "#{images_api_base}/[id]/destroy/?#{keys_uri}" }
|
11
|
-
let(:droplets_uri) { "#{droplets_api_base}/?#{keys_uri}" }
|
12
|
-
let(:droplet_find_uri) { "#{droplets_api_base}/[id]?#{keys_uri}" }
|
13
|
-
let(:droplet_stop_uri) { "#{droplets_api_base}/[id]/power_off/?#{keys_uri}" }
|
14
|
-
let(:droplet_start_uri) { "#{droplets_api_base}/[id]/power_on/?#{keys_uri}" }
|
15
|
-
let(:snapshot_uri) { "#{droplets_api_base}/[id]/snapshot/?name=[name]&#{keys_uri}" }
|
16
|
-
let(:event_find_uri) { "#{events_api_base}/[id]/?#{keys_uri}" }
|
17
|
-
|
18
|
-
# List of droplets
|
19
|
-
#
|
20
|
-
def stub_droplets
|
21
|
-
stub_without_id(droplets_uri, 'v1/show_droplets')
|
22
|
-
end
|
23
|
-
|
24
|
-
def stub_droplets_empty
|
25
|
-
stub_without_id(droplets_uri, 'v1/show_droplets_empty')
|
26
|
-
end
|
27
|
-
|
28
|
-
def stub_droplets_fail
|
29
|
-
stub_without_id(droplets_uri, 'v1/error_message')
|
30
|
-
end
|
31
|
-
|
32
|
-
# Droplet data
|
33
|
-
#
|
34
|
-
def stub_droplet(id)
|
35
|
-
stub_with_id(droplet_find_uri, id, 'v1/show_droplet')
|
36
|
-
end
|
37
|
-
|
38
|
-
def stub_droplet_fail(id)
|
39
|
-
stub_with_id(droplet_find_uri, id, 'v1/error_message')
|
40
|
-
end
|
41
|
-
|
42
|
-
def stub_droplet_inactive(id)
|
43
|
-
stub_with_id(droplet_find_uri, id, 'v1/show_droplet_inactive')
|
44
|
-
end
|
45
|
-
|
46
|
-
# Droplet actions
|
47
|
-
#
|
48
|
-
def stub_droplet_stop(id)
|
49
|
-
stub_with_id(droplet_stop_uri, id, 'v1/response_event')
|
50
|
-
end
|
51
|
-
|
52
|
-
def stub_droplet_stop_fail(id)
|
53
|
-
stub_with_id(droplet_stop_uri, id, 'v1/error_message')
|
54
|
-
end
|
55
|
-
|
56
|
-
def stub_droplet_start(id)
|
57
|
-
stub_with_id(droplet_start_uri, id, 'v1/response_event')
|
58
|
-
end
|
59
|
-
|
60
|
-
def stub_droplet_start_fail(id)
|
61
|
-
stub_with_id(droplet_start_uri, id, 'v1/error_message')
|
62
|
-
end
|
63
|
-
|
64
|
-
# Snapshot
|
65
|
-
#
|
66
|
-
def stub_droplet_snapshot(id, name)
|
67
|
-
stub_with_id_name(snapshot_uri, id, name, 'v1/response_event')
|
68
|
-
end
|
69
|
-
|
70
|
-
def stub_droplet_snapshot_fail(id, name)
|
71
|
-
stub_with_id_name(snapshot_uri, id, name, 'v1/error_message')
|
72
|
-
end
|
73
|
-
|
74
|
-
# Event status
|
75
|
-
#
|
76
|
-
def stub_event_done(id)
|
77
|
-
stub_with_id(event_find_uri, id, 'v1/show_event_done')
|
78
|
-
end
|
79
|
-
|
80
|
-
def stub_event_fail(id)
|
81
|
-
stub_with_id(event_find_uri, id, 'v1/error_message')
|
82
|
-
end
|
83
|
-
|
84
|
-
def stub_event_running(id)
|
85
|
-
stub_with_id(event_find_uri, id, 'v1/show_event_running')
|
86
|
-
end
|
87
|
-
|
88
|
-
# Image actions
|
89
|
-
#
|
90
|
-
def stub_image_destroy(id)
|
91
|
-
stub_with_id(image_destroy_uri, id, 'v1/response_event')
|
92
|
-
end
|
93
|
-
|
94
|
-
def stub_image_destroy_fail(id)
|
95
|
-
stub_with_id(image_destroy_uri, id, 'v1/error_message')
|
96
|
-
end
|
97
|
-
end
|