do_snapshot 0.0.14 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
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