do_snapshot 0.6.4 → 1.0.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 +9 -2
- data/bin/do_snapshot +1 -0
- data/lib/do_snapshot.rb +1 -0
- data/lib/do_snapshot/adapter.rb +10 -7
- data/lib/do_snapshot/adapter/abstract.rb +2 -1
- data/lib/do_snapshot/adapter/{digitalocean_v2.rb → droplet_kit.rb} +50 -33
- data/lib/do_snapshot/cli.rb +1 -0
- data/lib/do_snapshot/command.rb +1 -0
- data/lib/do_snapshot/configuration.rb +1 -0
- data/lib/do_snapshot/core_ext/hash.rb +1 -0
- data/lib/do_snapshot/distribution.rb +1 -0
- data/lib/do_snapshot/gem_ext/resource_kit.rb +30 -0
- data/lib/do_snapshot/helpers.rb +1 -0
- data/lib/do_snapshot/log.rb +1 -0
- data/lib/do_snapshot/mail.rb +1 -0
- data/lib/do_snapshot/rspec.rb +12 -0
- data/lib/do_snapshot/rspec/adapter.rb +265 -0
- data/lib/do_snapshot/rspec/api_helpers.rb +45 -0
- data/lib/do_snapshot/rspec/api_v2_helpers.rb +157 -0
- data/lib/do_snapshot/rspec/environment.rb +120 -0
- data/lib/do_snapshot/rspec/uri_helpers.rb +17 -0
- data/lib/do_snapshot/runner.rb +1 -0
- data/lib/do_snapshot/version.rb +2 -1
- data/spec/do_snapshot/adapter/abstract_spec.rb +2 -1
- data/spec/do_snapshot/adapter/droplet_kit_spec.rb +9 -0
- data/spec/do_snapshot/adapter_spec.rb +3 -2
- data/spec/do_snapshot/cli_spec.rb +4 -3
- data/spec/do_snapshot/command_spec.rb +4 -3
- data/spec/do_snapshot/configuration_spec.rb +1 -0
- data/spec/do_snapshot/log_spec.rb +2 -1
- data/spec/do_snapshot/mail_spec.rb +2 -1
- data/spec/do_snapshot/runner_spec.rb +3 -2
- data/spec/do_snapshot_spec.rb +2 -1
- data/spec/spec_helper.rb +2 -4
- data/spec/support/aruba.rb +1 -0
- data/spec/support/matchers.rb +1 -0
- metadata +47 -20
- data/spec/do_snapshot/adapter/digitalocean_v2_spec.rb +0 -264
- data/spec/shared/api_helpers.rb +0 -41
- data/spec/shared/api_v2_helpers.rb +0 -153
- data/spec/shared/environment.rb +0 -116
- data/spec/shared/uri_helpers.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb7ae5cc912690b2cd5850c46fd364ced760b5dd
|
4
|
+
data.tar.gz: a1664c690b7940bc93f6ae58904ff111af531551
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b2554982045d10d24c5d054ae03dd51cd7745412d64eb5da06dca91d0b3b46e5391ef71725ff3f8407ac86c9a4564963e362e6f2f8c3819db0fde574dcd0fe26
|
7
|
+
data.tar.gz: eb9d432913d910285373520713a695ac5572303517de158a13921f5d8bad1739c8bcc0b505d7a349c1b58454350c4ede9992c04052115fdbcece902353dc4c1f
|
data/README.md
CHANGED
@@ -13,6 +13,7 @@
|
|
13
13
|
Use this tool to backup DigitalOcean droplet's via snapshot method, on the fly!
|
14
14
|
|
15
15
|
## API Changes:
|
16
|
+
- 20.08.17: Change `Barge` to `DropletKit`. Release `1.0.0`.
|
16
17
|
- 03.08.16: DO now automagically keeps our droplets running when snapshot is processing, so:
|
17
18
|
Added options `--shutdown`, `--no-shutdown`.
|
18
19
|
`shutdown` now disabled by default, no downtime anymore, `YES`!
|
@@ -36,7 +37,13 @@ Here are some features:
|
|
36
37
|
|
37
38
|
## Compatibility
|
38
39
|
|
39
|
-
|
40
|
+
From `1.0.0`:
|
41
|
+
- Ruby version 2.0.0 or higher
|
42
|
+
- JRuby 9.1.0.0 or higher
|
43
|
+
|
44
|
+
Prior to `0.6.4`:
|
45
|
+
- Ruby version 1.9.3 or higher
|
46
|
+
- JRuby 1.7, 9.0.0.0 or higher
|
40
47
|
|
41
48
|
<img src="https://raw.githubusercontent.com/merqlove/do_snapshot/master/assets/example.png" style="max-width:100%" alt="DoSnaphot example">
|
42
49
|
|
@@ -195,7 +202,7 @@ Support this project and others by [merqlove](https://gratipay.com/~merqlove/) v
|
|
195
202
|
## Dependencies:
|
196
203
|
|
197
204
|
- [Thor](https://github.com/erikhuda/thor) for CLI.
|
198
|
-
- [
|
205
|
+
- [DropletKit](https://github.com/digitalocean/droplet_kit) for API V2 requests.
|
199
206
|
- [Pony](https://github.com/benprew/pony) for mail notifications.
|
200
207
|
|
201
208
|
## Contributing
|
data/bin/do_snapshot
CHANGED
data/lib/do_snapshot.rb
CHANGED
data/lib/do_snapshot/adapter.rb
CHANGED
@@ -1,29 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module DoSnapshot
|
2
3
|
# Adapter interface for API connections
|
3
4
|
# Ability to select DigitalOcean API versions.
|
4
5
|
#
|
5
6
|
module Adapter
|
6
7
|
autoload :Abstract, 'do_snapshot/adapter/abstract'
|
7
|
-
autoload :
|
8
|
+
autoload :DropletKit, 'do_snapshot/adapter/droplet_kit'
|
8
9
|
|
9
10
|
class << self
|
10
11
|
def api(protocol, options = {})
|
11
12
|
konst = find_protocol(protocol)
|
12
|
-
|
13
|
-
DoSnapshot::Adapter.const_defined?(konst)
|
13
|
+
error_protocol(protocol) unless DoSnapshot::Adapter.const_defined?(konst)
|
14
14
|
obj = DoSnapshot::Adapter.const_get(konst)
|
15
15
|
obj.new(options)
|
16
16
|
end
|
17
17
|
|
18
18
|
private
|
19
19
|
|
20
|
+
def error_protocol(protocol)
|
21
|
+
fail DoSnapshot::NoProtocolError, "Not existing protocol: #{protocol}."
|
22
|
+
end
|
23
|
+
|
20
24
|
def find_protocol(protocol)
|
21
|
-
if protocol.is_a?(
|
22
|
-
"DigitaloceanV#{protocol}"
|
23
|
-
elsif protocol.is_a?(String)
|
25
|
+
if protocol.is_a?(String)
|
24
26
|
protocol
|
25
27
|
else
|
26
|
-
|
28
|
+
error_protocol(protocol) if protocol.is_a?(Integer) && protocol < 2
|
29
|
+
'DropletKit'
|
27
30
|
end
|
28
31
|
end
|
29
32
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module DoSnapshot
|
4
5
|
module Adapter
|
@@ -25,7 +26,7 @@ module DoSnapshot
|
|
25
26
|
# noinspection RubyResolve
|
26
27
|
instance = droplet(id)
|
27
28
|
|
28
|
-
return power_on(id)
|
29
|
+
return power_on(id) if instance.respond_to?(:status) && !instance.status.include?('active')
|
29
30
|
|
30
31
|
logger.error "Droplet #{id} is still running. Skipping."
|
31
32
|
end
|
@@ -1,73 +1,86 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative '../gem_ext/resource_kit'
|
5
|
+
require 'droplet_kit' unless defined?(::DropletKit)
|
3
6
|
|
4
7
|
module DoSnapshot
|
5
8
|
module Adapter
|
6
9
|
# API for CLI commands
|
7
10
|
# Operating with Digital Ocean.
|
8
11
|
#
|
9
|
-
class
|
10
|
-
attr_reader :client
|
12
|
+
class DropletKit < Abstract
|
13
|
+
attr_reader :client, :per_page, :page
|
14
|
+
|
15
|
+
def initialize(*args)
|
16
|
+
@per_page = 1000
|
17
|
+
@page = 1
|
18
|
+
super(*args)
|
19
|
+
end
|
11
20
|
|
12
21
|
# Get single droplet from DigitalOcean
|
13
22
|
#
|
14
23
|
def droplet(id)
|
15
24
|
# noinspection RubyResolve
|
16
|
-
|
17
|
-
fail DropletFindError
|
18
|
-
|
25
|
+
result = client.droplets.find(id: id)
|
26
|
+
fail DropletFindError, id unless result
|
27
|
+
result
|
28
|
+
rescue ::DropletKit::Error => e
|
29
|
+
raise DropletFindError, id unless e.message
|
19
30
|
end
|
20
31
|
|
21
32
|
# Get droplets list from DigitalOcean
|
22
33
|
#
|
23
34
|
def droplets
|
24
35
|
# noinspection RubyResolve
|
25
|
-
response = client.
|
26
|
-
|
27
|
-
response
|
36
|
+
response = client.droplets.all(page: page, per_page: per_page)
|
37
|
+
response.many?
|
38
|
+
response
|
39
|
+
rescue ::NoMethodError => e
|
40
|
+
fail DropletListError, e
|
28
41
|
end
|
29
42
|
|
30
43
|
def snapshots(instance)
|
31
|
-
instance.snapshot_ids
|
44
|
+
instance.snapshot_ids if instance.respond_to?(:snapshot_ids)
|
32
45
|
end
|
33
46
|
|
34
47
|
# Request Power On for droplet
|
35
48
|
#
|
36
49
|
def power_on(id)
|
37
50
|
# noinspection RubyResolve
|
38
|
-
response = client.
|
51
|
+
response = client.droplet_actions.power_on(droplet_id: id)
|
39
52
|
|
40
|
-
|
41
|
-
|
42
|
-
if response.action.status.include?('in-progress')
|
53
|
+
if response.status.include?('in-progress')
|
43
54
|
logger.info "Droplet id: #{id} is requested for Power On."
|
44
55
|
else
|
45
56
|
logger.error "Droplet id: #{id} is failed to request for Power On."
|
46
57
|
end
|
58
|
+
rescue ::DropletKit::Error => e
|
59
|
+
fail DoSnapshot::EventError.new(id), e.message
|
47
60
|
end
|
48
61
|
|
49
62
|
# Power Off request for Droplet
|
50
63
|
#
|
51
64
|
def stop_droplet(id)
|
52
65
|
# noinspection RubyResolve,RubyResolve
|
53
|
-
response = client.
|
54
|
-
|
55
|
-
fail DropletShutdownError.new(id), response.message unless response.respond_to?(:action)
|
66
|
+
response = client.droplet_actions.power_off(droplet_id: id)
|
56
67
|
|
57
68
|
# noinspection RubyResolve
|
58
|
-
wait_shutdown(id, response.
|
69
|
+
wait_shutdown(id, response.id)
|
70
|
+
rescue ::DropletKit::Error => e
|
71
|
+
fail DropletShutdownError.new(id), e.message
|
59
72
|
end
|
60
73
|
|
61
74
|
# Sending event to create snapshot via DigitalOcean API and wait for success
|
62
75
|
#
|
63
76
|
def create_snapshot(id, name)
|
64
77
|
# noinspection RubyResolve,RubyResolve
|
65
|
-
response = client.
|
66
|
-
|
67
|
-
fail DoSnapshot::SnapshotCreateError.new(id), response.message unless response.respond_to?(:action)
|
78
|
+
response = client.droplet_actions.snapshot(droplet_id: id, name: name)
|
68
79
|
|
69
80
|
# noinspection RubyResolve
|
70
|
-
wait_event(response.
|
81
|
+
wait_event(response.id)
|
82
|
+
rescue ::DropletKit::Error => e
|
83
|
+
fail DoSnapshot::SnapshotCreateError.new(id), e.message
|
71
84
|
end
|
72
85
|
|
73
86
|
# Checking if droplet is powered off.
|
@@ -75,7 +88,7 @@ module DoSnapshot
|
|
75
88
|
def inactive?(id)
|
76
89
|
instance = droplet(id)
|
77
90
|
|
78
|
-
instance.status.include?('off')
|
91
|
+
instance.status.include?('off') if instance.respond_to?(:status)
|
79
92
|
end
|
80
93
|
|
81
94
|
# Cleanup our snapshots.
|
@@ -83,12 +96,8 @@ module DoSnapshot
|
|
83
96
|
def cleanup_snapshots(instance, size)
|
84
97
|
(0..size).each do |i|
|
85
98
|
# noinspection RubyResolve
|
86
|
-
snapshot = instance
|
87
|
-
|
88
|
-
|
89
|
-
logger.debug action unless action.success?
|
90
|
-
|
91
|
-
after_cleanup(instance.id, instance.name, snapshot, action)
|
99
|
+
snapshot = snapshots(instance)[i]
|
100
|
+
delete_image(instance, snapshot)
|
92
101
|
end
|
93
102
|
end
|
94
103
|
|
@@ -103,13 +112,21 @@ module DoSnapshot
|
|
103
112
|
#
|
104
113
|
def set_id
|
105
114
|
logger.debug 'Setting DigitalOcean Access Token.'
|
106
|
-
@client = ::
|
115
|
+
@client = ::DropletKit::Client.new(access_token: ENV['DIGITAL_OCEAN_ACCESS_TOKEN'])
|
107
116
|
end
|
108
117
|
|
109
118
|
protected
|
110
119
|
|
120
|
+
def delete_image(instance, snapshot) # rubocop:disable Metrics/AbcSize
|
121
|
+
action = client.images.delete(id: snapshot)
|
122
|
+
after_cleanup(instance.id, instance.name, snapshot, action)
|
123
|
+
rescue ::DropletKit::Error => e
|
124
|
+
logger.debug "#{snapshot} #{e.message}"
|
125
|
+
after_cleanup(instance.id, instance.name, snapshot, false)
|
126
|
+
end
|
127
|
+
|
111
128
|
def after_cleanup(droplet_id, droplet_name, snapshot, action)
|
112
|
-
if !action
|
129
|
+
if !action
|
113
130
|
logger.error "Destroy of snapshot #{snapshot} for droplet id: #{droplet_id} name: #{droplet_name} is failed."
|
114
131
|
else
|
115
132
|
logger.debug "Snapshot: #{snapshot} delete requested."
|
@@ -121,9 +138,9 @@ module DoSnapshot
|
|
121
138
|
def get_event_status(id, time)
|
122
139
|
return true if timeout?(id, time)
|
123
140
|
|
124
|
-
response = client.
|
141
|
+
response = client.actions.find(id: id)
|
125
142
|
|
126
|
-
fail DoSnapshot::EventError.new(id), response.message unless response.respond_to?(:
|
143
|
+
fail DoSnapshot::EventError.new(id), response.message unless response.respond_to?(:status)
|
127
144
|
|
128
145
|
# noinspection RubyResolve,RubyResolve
|
129
146
|
response.action.status.include?('completed') ? true : false
|
data/lib/do_snapshot/cli.rb
CHANGED
data/lib/do_snapshot/command.rb
CHANGED
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'resource_kit'
|
3
|
+
|
4
|
+
# TODO: Remove after `resource_kit` gem update.
|
5
|
+
ResourceKit::Action.class_eval do
|
6
|
+
def handler(*response_codes, &block)
|
7
|
+
if response_codes.empty?
|
8
|
+
handlers[:any] = block
|
9
|
+
else
|
10
|
+
response_codes.each do |code|
|
11
|
+
code = ResourceKit::StatusCodeMapper.code_for(code) unless code.is_a?(Integer)
|
12
|
+
handlers[code] = block
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# TODO: Remove after `resource_kit` gem update.
|
19
|
+
ResourceKit::ResourceCollection.class_eval do
|
20
|
+
def default_handler(*response_codes, &block)
|
21
|
+
if response_codes.empty?
|
22
|
+
default_handlers[:any] = block
|
23
|
+
else
|
24
|
+
response_codes.each do |code|
|
25
|
+
code = ResourceKit::StatusCodeMapper.code_for(code) unless code.is_a?(Integer)
|
26
|
+
default_handlers[code] = block
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/do_snapshot/helpers.rb
CHANGED
data/lib/do_snapshot/log.rb
CHANGED
data/lib/do_snapshot/mail.rb
CHANGED
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'rspec/core/shared_context'
|
3
|
+
|
4
|
+
module DoSnapshot
|
5
|
+
module RSpec # rubocop:disable Style/Documentation
|
6
|
+
autoload :Adapter, 'do_snapshot/rspec/adapter'
|
7
|
+
autoload :ApiHelpers, 'do_snapshot/rspec/api_helpers'
|
8
|
+
autoload :ApiV2Helpers, 'do_snapshot/rspec/api_v2_helpers'
|
9
|
+
autoload :Environment, 'do_snapshot/rspec/environment'
|
10
|
+
autoload :UriHelpers, 'do_snapshot/rspec/uri_helpers'
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,265 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module DoSnapshot
|
3
|
+
module RSpec
|
4
|
+
module Adapter # rubocop:disable Style/Documentation,Metrics/ModuleLength
|
5
|
+
extend ::RSpec::Core::SharedContext
|
6
|
+
|
7
|
+
subject(:api) { described_class }
|
8
|
+
subject(:log) { DoSnapshot::Log }
|
9
|
+
|
10
|
+
describe '.initialize' do
|
11
|
+
describe '#delay' do
|
12
|
+
let(:delay) { 5 }
|
13
|
+
let(:instance) { api.new(delay: delay) }
|
14
|
+
it('with custom delay') { expect(instance.delay).to eq delay }
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#timeout' do
|
18
|
+
let(:timeout) { 5 }
|
19
|
+
let(:instance) { api.new(timeout: timeout) }
|
20
|
+
it('with custom timeout') { expect(instance.timeout).to eq timeout }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'droplets' do
|
25
|
+
let(:instance) { api.new(delay: delay, timeout: timeout) }
|
26
|
+
include UriHelpers
|
27
|
+
|
28
|
+
describe '.droplet' do
|
29
|
+
it 'with droplet' do
|
30
|
+
stub_droplet(droplet_id)
|
31
|
+
|
32
|
+
instance.droplet(droplet_id)
|
33
|
+
|
34
|
+
expect(a_request(:get, droplet_url))
|
35
|
+
.to have_been_made
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'with error' do
|
39
|
+
stub_droplet_fail(droplet_id)
|
40
|
+
|
41
|
+
expect { instance.droplet(droplet_id) }
|
42
|
+
.to raise_error(DoSnapshot::DropletFindError)
|
43
|
+
expect(DoSnapshot.logger.buffer)
|
44
|
+
.to include "Droplet id: #{droplet_id} Not Found"
|
45
|
+
|
46
|
+
expect(a_request(:get, droplet_url))
|
47
|
+
.to have_been_made
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '.droplets' do
|
52
|
+
it 'with droplets' do
|
53
|
+
stub_droplets
|
54
|
+
|
55
|
+
expect(instance.droplets.many?).to be_truthy
|
56
|
+
|
57
|
+
expect(a_request(:get, droplets_uri))
|
58
|
+
.to have_been_made
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'with error' do
|
62
|
+
stub_droplets_fail
|
63
|
+
|
64
|
+
expect { instance.droplets }.to raise_error(DoSnapshot::DropletListError)
|
65
|
+
expect(DoSnapshot.logger.buffer)
|
66
|
+
.to include 'Droplet Listing is failed to retrieve'
|
67
|
+
|
68
|
+
expect(a_request(:get, droplets_uri))
|
69
|
+
.to have_been_made
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe '.start_droplet' do
|
74
|
+
it 'with event' do
|
75
|
+
stub_droplet_inactive(droplet_id)
|
76
|
+
stub_droplet_start(droplet_id)
|
77
|
+
|
78
|
+
instance.start_droplet(droplet_id)
|
79
|
+
expect(DoSnapshot.logger.buffer).to include "Droplet id: #{droplet_id} is requested for Power On."
|
80
|
+
|
81
|
+
expect(a_request(:post, droplet_start_url))
|
82
|
+
.to have_been_made
|
83
|
+
expect(a_request(:get, droplet_url))
|
84
|
+
.to have_been_made
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'with warning message' do
|
88
|
+
stub_droplet(droplet_id)
|
89
|
+
|
90
|
+
expect { instance.start_droplet(droplet_id) }
|
91
|
+
.not_to raise_error
|
92
|
+
expect(DoSnapshot.logger.buffer)
|
93
|
+
.to include "Droplet #{droplet_id} is still running. Skipping."
|
94
|
+
|
95
|
+
expect(a_request(:get, droplet_url))
|
96
|
+
.to have_been_made
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'with error' do
|
100
|
+
stub_droplet_fail(droplet_id)
|
101
|
+
|
102
|
+
expect { instance.start_droplet(droplet_id) }
|
103
|
+
.to raise_error(DoSnapshot::DropletFindError)
|
104
|
+
|
105
|
+
expect(a_request(:get, droplet_url))
|
106
|
+
.to have_been_made
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '.stop_droplet by power status' do
|
111
|
+
let(:instance) { api.new(delay: delay, timeout: timeout, stop_by: :power_status) }
|
112
|
+
|
113
|
+
it 'with success' do
|
114
|
+
stub_event_done(event_id)
|
115
|
+
stub_droplet_stop(droplet_id)
|
116
|
+
stub_droplet_inactive(droplet_id)
|
117
|
+
|
118
|
+
instance.stop_droplet(droplet_id)
|
119
|
+
|
120
|
+
expect(a_request(:post, droplet_stop_url))
|
121
|
+
.to have_been_made
|
122
|
+
expect(a_request(:get, droplet_url))
|
123
|
+
.to have_been_made
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'with error' do
|
127
|
+
stub_droplet_stop_fail(droplet_id)
|
128
|
+
stub_droplet(droplet_id)
|
129
|
+
instance.timeout = 1
|
130
|
+
expect { instance.stop_droplet(droplet_id) }
|
131
|
+
.to raise_error(DoSnapshot::DropletShutdownError)
|
132
|
+
instance.timeout = timeout
|
133
|
+
expect(DoSnapshot.logger.buffer)
|
134
|
+
.to include 'Droplet id: 100823 is Failed to Power Off.'
|
135
|
+
|
136
|
+
expect(a_request(:post, droplet_stop_url))
|
137
|
+
.to have_been_made
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe '.stop_droplet by event' do
|
142
|
+
it 'with success' do
|
143
|
+
stub_event_done(event_id)
|
144
|
+
stub_droplet_stop(droplet_id)
|
145
|
+
|
146
|
+
instance.stop_droplet(droplet_id)
|
147
|
+
|
148
|
+
expect(a_request(:post, droplet_stop_url))
|
149
|
+
.to have_been_made
|
150
|
+
expect(a_request(:get, action_find_url))
|
151
|
+
.to have_been_made
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'with error' do
|
155
|
+
stub_droplet_stop_fail(droplet_id)
|
156
|
+
|
157
|
+
expect { instance.stop_droplet(droplet_id) }
|
158
|
+
.to raise_error(DoSnapshot::DropletShutdownError)
|
159
|
+
expect(DoSnapshot.logger.buffer)
|
160
|
+
.to include 'Droplet id: 100823 is Failed to Power Off.'
|
161
|
+
|
162
|
+
expect(a_request(:post, droplet_stop_url))
|
163
|
+
.to have_been_made
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
describe '.create_snapshot' do
|
168
|
+
it 'with success' do
|
169
|
+
stub_event_done(event_id)
|
170
|
+
stub_droplet_snapshot(droplet_id, snapshot_name)
|
171
|
+
|
172
|
+
expect { instance.create_snapshot(droplet_id, snapshot_name) }
|
173
|
+
.not_to raise_error
|
174
|
+
|
175
|
+
expect(a_request(:post, droplet_snapshot_url))
|
176
|
+
.to have_been_made
|
177
|
+
expect(a_request(:get, action_find_url))
|
178
|
+
.to have_been_made
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'with error' do
|
182
|
+
stub_droplet_snapshot_fail(droplet_id, snapshot_name)
|
183
|
+
|
184
|
+
expect { instance.create_snapshot(droplet_id, snapshot_name) }
|
185
|
+
.to raise_error(DoSnapshot::SnapshotCreateError)
|
186
|
+
|
187
|
+
expect(a_request(:post, droplet_snapshot_url))
|
188
|
+
.to have_been_made
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'with event error' do
|
192
|
+
stub_droplet_snapshot(droplet_id, snapshot_name)
|
193
|
+
stub_event_fail(event_id)
|
194
|
+
|
195
|
+
expect { instance.create_snapshot(droplet_id, snapshot_name) }
|
196
|
+
.not_to raise_error
|
197
|
+
expect(DoSnapshot.logger.buffer)
|
198
|
+
.to include "Event id: #{event_id} is failed!"
|
199
|
+
|
200
|
+
expect(a_request(:post, droplet_snapshot_url))
|
201
|
+
.to have_been_made
|
202
|
+
expect(a_request(:get, action_find_url))
|
203
|
+
.to have_been_made
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
describe '.inactive?' do
|
208
|
+
it 'when inactive' do
|
209
|
+
stub_droplet_inactive(droplet_id)
|
210
|
+
|
211
|
+
expect(instance.inactive?(droplet_id))
|
212
|
+
.to be_truthy
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'when active' do
|
216
|
+
stub_droplet(droplet_id)
|
217
|
+
|
218
|
+
expect(instance.inactive?(droplet_id))
|
219
|
+
.to be_falsey
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
describe '.cleanup_snapshots' do
|
224
|
+
it 'with success' do
|
225
|
+
stub_droplet(droplet_id)
|
226
|
+
stub_image_destroy(image_id)
|
227
|
+
stub_image_destroy(image_id2)
|
228
|
+
|
229
|
+
droplet = instance.droplet(droplet_id)
|
230
|
+
expect { instance.cleanup_snapshots(droplet, 1) }
|
231
|
+
.not_to raise_error
|
232
|
+
expect(DoSnapshot.logger.buffer)
|
233
|
+
.to include 'Snapshot: 5019770 delete requested.'
|
234
|
+
|
235
|
+
expect(a_request(:get, droplet_url))
|
236
|
+
.to have_been_made
|
237
|
+
expect(a_request(:delete, image_destroy_url))
|
238
|
+
.to have_been_made
|
239
|
+
expect(a_request(:delete, image_destroy2_url))
|
240
|
+
.to have_been_made
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'with warning message' do
|
244
|
+
stub_droplet(droplet_id)
|
245
|
+
stub_image_destroy_fail(image_id)
|
246
|
+
stub_image_destroy_fail(image_id2)
|
247
|
+
|
248
|
+
droplet = instance.droplet(droplet_id)
|
249
|
+
expect { instance.cleanup_snapshots(droplet, 1) }
|
250
|
+
.not_to raise_error
|
251
|
+
expect(DoSnapshot.logger.buffer)
|
252
|
+
.to include 'Destroy of snapshot 5019903 for droplet id: 100823 name: example.com is failed.'
|
253
|
+
|
254
|
+
expect(a_request(:get, droplet_url))
|
255
|
+
.to have_been_made
|
256
|
+
expect(a_request(:delete, image_destroy_url))
|
257
|
+
.to have_been_made
|
258
|
+
expect(a_request(:delete, image_destroy2_url))
|
259
|
+
.to have_been_made
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|