do_snapshot 0.0.14 → 0.0.15

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +29 -7
  3. data/lib/do_snapshot/adapter.rb +21 -0
  4. data/lib/do_snapshot/adapter/abstract.rb +44 -0
  5. data/lib/do_snapshot/adapter/digitalocean.rb +133 -0
  6. data/lib/do_snapshot/adapter/digitalocean_v2.rb +145 -0
  7. data/lib/do_snapshot/cli.rb +22 -12
  8. data/lib/do_snapshot/command.rb +7 -8
  9. data/lib/do_snapshot/version.rb +1 -1
  10. data/spec/do_snapshot/adapter/abstract_spec.rb +29 -0
  11. data/spec/do_snapshot/{api_spec.rb → adapter/digitalocean_spec.rb} +4 -3
  12. data/spec/do_snapshot/adapter/digitalocean_v2_spec.rb +223 -0
  13. data/spec/do_snapshot/cli_spec.rb +2 -1
  14. data/spec/do_snapshot/command_spec.rb +5 -8
  15. data/spec/fixtures/{error_message.json → digitalocean/v1/error_message.json} +0 -0
  16. data/spec/fixtures/{response_event.json → digitalocean/v1/response_event.json} +0 -0
  17. data/spec/fixtures/{show_droplet.json → digitalocean/v1/show_droplet.json} +0 -0
  18. data/spec/fixtures/{show_droplet_inactive.json → digitalocean/v1/show_droplet_inactive.json} +0 -0
  19. data/spec/fixtures/{show_droplets.json → digitalocean/v1/show_droplets.json} +0 -0
  20. data/spec/fixtures/{show_droplets_empty.json → digitalocean/v1/show_droplets_empty.json} +0 -0
  21. data/spec/fixtures/{show_event_done.json → digitalocean/v1/show_event_done.json} +0 -0
  22. data/spec/fixtures/{show_event_start.json → digitalocean/v1/show_event_start.json} +0 -0
  23. data/spec/fixtures/digitalocean/v2/empty.json +0 -0
  24. data/spec/fixtures/digitalocean/v2/error_message.json +4 -0
  25. data/spec/fixtures/digitalocean/v2/response_event.json +29 -0
  26. data/spec/fixtures/digitalocean/v2/show_droplet.json +102 -0
  27. data/spec/fixtures/digitalocean/v2/show_droplet_inactive.json +102 -0
  28. data/spec/fixtures/digitalocean/v2/show_droplets.json +284 -0
  29. data/spec/fixtures/digitalocean/v2/show_droplets_empty.json +5 -0
  30. data/spec/fixtures/digitalocean/v2/show_event_done.json +29 -0
  31. data/spec/fixtures/digitalocean/v2/show_event_power_off_done.json +29 -0
  32. data/spec/fixtures/digitalocean/v2/show_event_power_off_start.json +29 -0
  33. data/spec/fixtures/digitalocean/v2/show_event_power_on_done.json +29 -0
  34. data/spec/fixtures/digitalocean/v2/show_event_power_on_start.json +29 -0
  35. data/spec/fixtures/digitalocean/v2/show_event_start.json +29 -0
  36. data/spec/shared/api_helpers.rb +5 -80
  37. data/spec/shared/api_v1_helpers.rb +97 -0
  38. data/spec/shared/api_v2_helpers.rb +152 -0
  39. data/spec/shared/environment.rb +5 -14
  40. data/spec/shared/uri_helpers.rb +1 -0
  41. data/spec/spec_helper.rb +5 -3
  42. metadata +74 -23
  43. data/lib/do_snapshot/api.rb +0 -144
@@ -6,13 +6,14 @@ shared_context 'spec' do
6
6
 
7
7
  let(:client_key) { 'foo' }
8
8
  let(:api_key) { 'bar' }
9
+ let(:access_token) { 'sometoken' }
9
10
  let(:event_id) { '7501' }
10
11
  let(:droplet_id) { '100823' }
11
12
  let(:image_id) { '5019770' }
12
13
  let(:image_id2) { '5019903' }
13
- let(:cli_keys) { Thor::CoreExt::HashWithIndifferentAccess.new(digital_ocean_client_id: 'NOTFOO', digital_ocean_client_bar: 'NOTBAR') }
14
+ let(:cli_keys) { Thor::CoreExt::HashWithIndifferentAccess.new(digital_ocean_client_id: 'NOTFOO', digital_ocean_client_key: 'NOTBAR', digital_ocean_access_token: 'NOTTOK') }
14
15
  let(:snapshot_name) { "foo_#{DateTime.now.strftime('%Y_%m_%d')}" }
15
- let(:default_options) { Hash[only: %w( 100823 ), exclude: %w(), keep: 3, stop: false, trace: true, clean: true, delay: 0, timeout: 600, droplets: nil, threads: []] }
16
+ let(:default_options) { Hash[protocol: 1, only: %w( 100823 ), exclude: %w(), keep: 3, stop: false, trace: true, clean: true, delay: 0, timeout: 600, droplets: nil, threads: []] }
16
17
  let(:no_exclude) { [] }
17
18
  let(:exclude) { %w( 100824 100825 ) }
18
19
  let(:no_only) { [] }
@@ -28,18 +29,6 @@ shared_context 'spec' do
28
29
  let(:mail_options) { Thor::CoreExt::HashWithIndifferentAccess.new(to: 'mail@somehost.com', from: 'from@host.com') }
29
30
  let(:smtp_options) { Thor::CoreExt::HashWithIndifferentAccess.new(address: 'smtp.gmail.com', port: '25', user_name: 'someuser', password: 'somepassword') }
30
31
  let(:log) { Thor::CoreExt::HashWithIndifferentAccess.new(log: "#{project_path}/log/test.log") }
31
- let(:api_base) { 'https://api.digitalocean.com/v1' }
32
- let(:keys_uri) { "api_key=#{api_key}&client_id=#{client_key}" }
33
- let(:droplets_api_base) { "#{api_base}/droplets" }
34
- let(:events_api_base) { "#{api_base}/events" }
35
- let(:images_api_base) { "#{api_base}/images" }
36
- let(:image_destroy_uri) { "#{images_api_base}/[id]/destroy/?#{keys_uri}" }
37
- let(:droplets_uri) { "#{droplets_api_base}/?#{keys_uri}" }
38
- let(:droplet_find_uri) { "#{droplets_api_base}/[id]?#{keys_uri}" }
39
- let(:droplet_stop_uri) { "#{droplets_api_base}/[id]/power_off/?#{keys_uri}" }
40
- let(:droplet_start_uri) { "#{droplets_api_base}/[id]/power_on/?#{keys_uri}" }
41
- let(:snapshot_uri) { "#{droplets_api_base}/[id]/snapshot/?name=[name]&#{keys_uri}" }
42
- let(:event_find_uri) { "#{events_api_base}/[id]/?#{keys_uri}" }
43
32
 
44
33
  def stub_all_api(droplets = nil, active = false) # rubocop:disable MethodLength
45
34
  drops = []
@@ -87,11 +76,13 @@ shared_context 'spec' do
87
76
  def reset_api_keys
88
77
  ENV['DIGITAL_OCEAN_API_KEY'] = nil
89
78
  ENV['DIGITAL_OCEAN_CLIENT_ID'] = nil
79
+ ENV['DIGITAL_OCEAN_ACCESS_TOKEN'] = nil
90
80
  end
91
81
 
92
82
  def set_api_keys
93
83
  ENV['DIGITAL_OCEAN_API_KEY'] = api_key
94
84
  ENV['DIGITAL_OCEAN_CLIENT_ID'] = client_key
85
+ ENV['DIGITAL_OCEAN_ACCESS_TOKEN'] = access_token
95
86
  end
96
87
 
97
88
  before(:all) do
@@ -8,5 +8,6 @@ shared_context 'uri_helpers' do
8
8
  let(:event_find_url) { url_with_id(event_find_uri, event_id) }
9
9
  let(:image_destroy_url) { url_with_id(image_destroy_uri, image_id) }
10
10
  let(:image_destroy2_url) { url_with_id(image_destroy_uri, image_id2) }
11
+ let(:action_find_url) { url_with_id(action_find_uri, event_id) }
11
12
  let(:droplet_snapshot_url) { url_with_id_name(snapshot_uri, droplet_id, snapshot_name) }
12
13
  end
data/spec/spec_helper.rb CHANGED
@@ -7,18 +7,20 @@ end
7
7
 
8
8
  require 'do_snapshot/cli'
9
9
  require 'webmock/rspec'
10
- require 'digitalocean'
10
+ require 'digitalocean_c'
11
11
  require_relative 'shared/api_helpers'
12
+ require_relative 'shared/api_v1_helpers'
13
+ require_relative 'shared/api_v2_helpers'
12
14
  require_relative 'shared/uri_helpers'
13
15
  require_relative 'shared/environment'
14
16
  require 'do_snapshot/core_ext/hash'
15
17
 
16
18
  WebMock.disable_net_connect!(allow_localhost: true)
19
+ WebMock.disable!(except: [:net_http])
17
20
 
18
21
  RSpec.configure do |config|
19
22
  # Pretty tests
20
23
  config.color = true
21
-
22
24
  config.order = :random
23
25
  config.mock_with :rspec do |mocks|
24
26
  mocks.verify_doubled_constant_names = true
@@ -30,7 +32,7 @@ def project_path
30
32
  end
31
33
 
32
34
  def fixture(fixture_name)
33
- File.new(project_path + "/spec/fixtures/#{fixture_name}.json")
35
+ Pathname.new(project_path + '/spec/fixtures/digitalocean/').join("#{fixture_name}.json").read
34
36
  end
35
37
 
36
38
  Dir[File.expand_path(File.join(File.dirname(__FILE__), 'support', '**', '*.rb'))].each { |f| require f }
metadata CHANGED
@@ -1,17 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: do_snapshot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.14
4
+ version: 0.0.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Merkulov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-14 00:00:00.000000000 Z
11
+ date: 2015-05-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: digitalocean
14
+ name: digitalocean_c
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: droplet_kit
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
31
  - - "~>"
@@ -64,7 +78,10 @@ files:
64
78
  - README.md
65
79
  - bin/do_snapshot
66
80
  - lib/do_snapshot.rb
67
- - lib/do_snapshot/api.rb
81
+ - lib/do_snapshot/adapter.rb
82
+ - lib/do_snapshot/adapter/abstract.rb
83
+ - lib/do_snapshot/adapter/digitalocean.rb
84
+ - lib/do_snapshot/adapter/digitalocean_v2.rb
68
85
  - lib/do_snapshot/cli.rb
69
86
  - lib/do_snapshot/command.rb
70
87
  - lib/do_snapshot/core_ext/hash.rb
@@ -73,19 +90,36 @@ files:
73
90
  - lib/do_snapshot/mail.rb
74
91
  - lib/do_snapshot/version.rb
75
92
  - spec/.keep
76
- - spec/do_snapshot/api_spec.rb
93
+ - spec/do_snapshot/adapter/abstract_spec.rb
94
+ - spec/do_snapshot/adapter/digitalocean_spec.rb
95
+ - spec/do_snapshot/adapter/digitalocean_v2_spec.rb
77
96
  - spec/do_snapshot/cli_spec.rb
78
97
  - spec/do_snapshot/command_spec.rb
79
98
  - spec/do_snapshots_spec.rb
80
- - spec/fixtures/error_message.json
81
- - spec/fixtures/response_event.json
82
- - spec/fixtures/show_droplet.json
83
- - spec/fixtures/show_droplet_inactive.json
84
- - spec/fixtures/show_droplets.json
85
- - spec/fixtures/show_droplets_empty.json
86
- - spec/fixtures/show_event_done.json
87
- - spec/fixtures/show_event_start.json
99
+ - spec/fixtures/digitalocean/v1/error_message.json
100
+ - spec/fixtures/digitalocean/v1/response_event.json
101
+ - spec/fixtures/digitalocean/v1/show_droplet.json
102
+ - spec/fixtures/digitalocean/v1/show_droplet_inactive.json
103
+ - spec/fixtures/digitalocean/v1/show_droplets.json
104
+ - spec/fixtures/digitalocean/v1/show_droplets_empty.json
105
+ - spec/fixtures/digitalocean/v1/show_event_done.json
106
+ - spec/fixtures/digitalocean/v1/show_event_start.json
107
+ - spec/fixtures/digitalocean/v2/empty.json
108
+ - spec/fixtures/digitalocean/v2/error_message.json
109
+ - spec/fixtures/digitalocean/v2/response_event.json
110
+ - spec/fixtures/digitalocean/v2/show_droplet.json
111
+ - spec/fixtures/digitalocean/v2/show_droplet_inactive.json
112
+ - spec/fixtures/digitalocean/v2/show_droplets.json
113
+ - spec/fixtures/digitalocean/v2/show_droplets_empty.json
114
+ - spec/fixtures/digitalocean/v2/show_event_done.json
115
+ - spec/fixtures/digitalocean/v2/show_event_power_off_done.json
116
+ - spec/fixtures/digitalocean/v2/show_event_power_off_start.json
117
+ - spec/fixtures/digitalocean/v2/show_event_power_on_done.json
118
+ - spec/fixtures/digitalocean/v2/show_event_power_on_start.json
119
+ - spec/fixtures/digitalocean/v2/show_event_start.json
88
120
  - spec/shared/api_helpers.rb
121
+ - spec/shared/api_v1_helpers.rb
122
+ - spec/shared/api_v2_helpers.rb
89
123
  - spec/shared/environment.rb
90
124
  - spec/shared/uri_helpers.rb
91
125
  - spec/spec_helper.rb
@@ -101,7 +135,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
101
135
  requirements:
102
136
  - - ">="
103
137
  - !ruby/object:Gem::Version
104
- version: '0'
138
+ version: '2.0'
105
139
  required_rubygems_version: !ruby/object:Gem::Requirement
106
140
  requirements:
107
141
  - - ">="
@@ -116,19 +150,36 @@ summary: A command-line snapshot maker for your DigitalOcean droplets. Fully Aut
116
150
  Multi-threaded.
117
151
  test_files:
118
152
  - spec/.keep
119
- - spec/do_snapshot/api_spec.rb
153
+ - spec/do_snapshot/adapter/abstract_spec.rb
154
+ - spec/do_snapshot/adapter/digitalocean_spec.rb
155
+ - spec/do_snapshot/adapter/digitalocean_v2_spec.rb
120
156
  - spec/do_snapshot/cli_spec.rb
121
157
  - spec/do_snapshot/command_spec.rb
122
158
  - spec/do_snapshots_spec.rb
123
- - spec/fixtures/error_message.json
124
- - spec/fixtures/response_event.json
125
- - spec/fixtures/show_droplet.json
126
- - spec/fixtures/show_droplet_inactive.json
127
- - spec/fixtures/show_droplets.json
128
- - spec/fixtures/show_droplets_empty.json
129
- - spec/fixtures/show_event_done.json
130
- - spec/fixtures/show_event_start.json
159
+ - spec/fixtures/digitalocean/v1/error_message.json
160
+ - spec/fixtures/digitalocean/v1/response_event.json
161
+ - spec/fixtures/digitalocean/v1/show_droplet.json
162
+ - spec/fixtures/digitalocean/v1/show_droplet_inactive.json
163
+ - spec/fixtures/digitalocean/v1/show_droplets.json
164
+ - spec/fixtures/digitalocean/v1/show_droplets_empty.json
165
+ - spec/fixtures/digitalocean/v1/show_event_done.json
166
+ - spec/fixtures/digitalocean/v1/show_event_start.json
167
+ - spec/fixtures/digitalocean/v2/empty.json
168
+ - spec/fixtures/digitalocean/v2/error_message.json
169
+ - spec/fixtures/digitalocean/v2/response_event.json
170
+ - spec/fixtures/digitalocean/v2/show_droplet.json
171
+ - spec/fixtures/digitalocean/v2/show_droplet_inactive.json
172
+ - spec/fixtures/digitalocean/v2/show_droplets.json
173
+ - spec/fixtures/digitalocean/v2/show_droplets_empty.json
174
+ - spec/fixtures/digitalocean/v2/show_event_done.json
175
+ - spec/fixtures/digitalocean/v2/show_event_power_off_done.json
176
+ - spec/fixtures/digitalocean/v2/show_event_power_off_start.json
177
+ - spec/fixtures/digitalocean/v2/show_event_power_on_done.json
178
+ - spec/fixtures/digitalocean/v2/show_event_power_on_start.json
179
+ - spec/fixtures/digitalocean/v2/show_event_start.json
131
180
  - spec/shared/api_helpers.rb
181
+ - spec/shared/api_v1_helpers.rb
182
+ - spec/shared/api_v2_helpers.rb
132
183
  - spec/shared/environment.rb
133
184
  - spec/shared/uri_helpers.rb
134
185
  - spec/spec_helper.rb
@@ -1,144 +0,0 @@
1
- # -*- encoding : utf-8 -*-
2
- require 'digitalocean'
3
-
4
- module DoSnapshot
5
- # API for CLI commands
6
- # Operating with Digital Ocean.
7
- #
8
- class API
9
- attr_accessor :delay
10
- attr_accessor :timeout
11
-
12
- def initialize(options)
13
- set_id
14
- options.each_pair do |key, option|
15
- send("#{key}=", option)
16
- end
17
- end
18
-
19
- # Get single droplet from DigitalOcean
20
- #
21
- def droplet(id)
22
- # noinspection RubyResolve
23
- instance = Digitalocean::Droplet.find(id)
24
- fail DropletFindError, instance.message unless instance.status.include? 'OK'
25
- instance
26
- end
27
-
28
- # Get droplets list from DigitalOcean
29
- #
30
- def droplets
31
- # noinspection RubyResolve
32
- droplets = Digitalocean::Droplet.all
33
- fail DropletListError, droplets.message unless droplets.status.include? 'OK'
34
- droplets
35
- end
36
-
37
- # Power On request for Droplet
38
- #
39
- def start_droplet(id)
40
- # noinspection RubyResolve
41
- instance = Digitalocean::Droplet.find(id)
42
-
43
- fail unless instance.status.include? 'OK'
44
-
45
- if instance.droplet.status.include? 'active'
46
- Log.error 'Droplet is still running.'
47
- else
48
- power_on id
49
- end
50
- end
51
-
52
- # Power Off request for Droplet
53
- #
54
- def stop_droplet(id)
55
- # noinspection RubyResolve,RubyResolve
56
- event = Digitalocean::Droplet.power_off(id)
57
-
58
- fail event.message unless event.status.include? 'OK'
59
-
60
- # noinspection RubyResolve
61
- wait_event(event.event_id)
62
- rescue => e
63
- raise DropletShutdownError.new(id), e.message, e.backtrace
64
- end
65
-
66
- # Sending event to create snapshot via DigitalOcean API and wait for success
67
- #
68
- def create_snapshot(id, name)
69
- # noinspection RubyResolve,RubyResolve
70
- event = Digitalocean::Droplet.snapshot(id, name: name)
71
-
72
- if !event
73
- fail 'Something wrong with DigitalOcean or with your connection :)'
74
- elsif event && !event.status.include?('OK')
75
- fail event.message
76
- end
77
-
78
- # noinspection RubyResolve
79
- wait_event(event.event_id)
80
- end
81
-
82
- # Cleanup our snapshots.
83
- #
84
- def cleanup_snapshots(instance, size) # rubocop:disable MethodLength
85
- (0..size).each do |i|
86
- # noinspection RubyResolve
87
- snapshot = instance.snapshots[i]
88
- event = Digitalocean::Image.destroy(snapshot.id)
89
-
90
- after_cleanup(instance.id, instance.name, snapshot, event)
91
- end
92
- end
93
-
94
- protected
95
-
96
- # Set id's of Digital Ocean API.
97
- #
98
- def set_id
99
- Log.debug 'Setting DigitalOcean Id\'s.'
100
- Digitalocean.client_id = ENV['DIGITAL_OCEAN_CLIENT_ID']
101
- Digitalocean.api_key = ENV['DIGITAL_OCEAN_API_KEY']
102
- end
103
-
104
- # Waiting for event exit
105
- def wait_event(id)
106
- time = Time.now
107
- sleep(delay) until get_event_status(id, time)
108
- end
109
-
110
- # Looking for event status.
111
- # Before snapshot we to know that machine has powered off.
112
- #
113
- def get_event_status(id, time)
114
- return true if (Time.now - time) > timeout
115
- event = Digitalocean::Event.find(id)
116
- fail event.message unless event.status.include?('OK')
117
- # noinspection RubyResolve,RubyResolve
118
- event.event.percentage && event.event.percentage.include?('100') ? true : false
119
- end
120
-
121
- # Request Power On for droplet
122
- #
123
- def power_on(id)
124
- # noinspection RubyResolve
125
- event = Digitalocean::Droplet.power_on(id)
126
- case event && event.status
127
- when 'OK'
128
- Log.info 'Power On has been requested.'
129
- else
130
- Log.error 'Power On failed to request.'
131
- end
132
- end
133
-
134
- def after_cleanup(droplet_id, droplet_name, snapshot, event)
135
- if !event
136
- Log.error "Destroy of snapshot #{snapshot.name} for droplet id: #{droplet_id} name: #{droplet_name} is failed."
137
- elsif event && !event.status.include?('OK')
138
- Log.error event.message
139
- else
140
- Log.debug "Snapshot name: #{snapshot.name} delete requested."
141
- end
142
- end
143
- end
144
- end