droplet_kit 1.2.3 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/droplet_kit.gemspec +2 -2
  4. data/lib/droplet_kit.rb +20 -3
  5. data/lib/droplet_kit/client.rb +2 -0
  6. data/lib/droplet_kit/error_handling_resourcable.rb +19 -0
  7. data/lib/droplet_kit/mappings/domain_record_mapping.rb +6 -6
  8. data/lib/droplet_kit/mappings/floating_ip_mapping.rb +19 -0
  9. data/lib/droplet_kit/models/floating_ip.rb +10 -0
  10. data/lib/droplet_kit/paginated_resource.rb +1 -1
  11. data/lib/droplet_kit/resources/account_resource.rb +2 -0
  12. data/lib/droplet_kit/resources/action_resource.rb +2 -0
  13. data/lib/droplet_kit/resources/domain_record_resource.rb +2 -0
  14. data/lib/droplet_kit/resources/domain_resource.rb +2 -0
  15. data/lib/droplet_kit/resources/droplet_action_resource.rb +4 -0
  16. data/lib/droplet_kit/resources/droplet_resource.rb +3 -1
  17. data/lib/droplet_kit/resources/droplet_upgrade_resource.rb +2 -0
  18. data/lib/droplet_kit/resources/floating_ip_action_resource.rb +30 -0
  19. data/lib/droplet_kit/resources/floating_ip_resource.rb +29 -0
  20. data/lib/droplet_kit/resources/image_action_resource.rb +4 -0
  21. data/lib/droplet_kit/resources/image_resource.rb +2 -0
  22. data/lib/droplet_kit/resources/region_resource.rb +2 -0
  23. data/lib/droplet_kit/resources/size_resource.rb +2 -0
  24. data/lib/droplet_kit/resources/ssh_key_resource.rb +2 -0
  25. data/lib/droplet_kit/version.rb +1 -1
  26. data/spec/fixtures/droplet_actions/change_kernel.json +27 -0
  27. data/spec/fixtures/droplet_actions/disable_backups.json +27 -0
  28. data/spec/fixtures/droplet_actions/enable_ipv6.json +27 -0
  29. data/spec/fixtures/droplet_actions/enable_private_networking.json +27 -0
  30. data/spec/fixtures/droplet_actions/find.json +19 -0
  31. data/spec/fixtures/droplet_actions/password_reset.json +27 -0
  32. data/spec/fixtures/droplet_actions/power_cycle.json +27 -0
  33. data/spec/fixtures/droplet_actions/power_off.json +27 -0
  34. data/spec/fixtures/droplet_actions/power_on.json +27 -0
  35. data/spec/fixtures/droplet_actions/reboot.json +27 -0
  36. data/spec/fixtures/droplet_actions/rebuild.json +27 -0
  37. data/spec/fixtures/droplet_actions/rename.json +27 -0
  38. data/spec/fixtures/droplet_actions/resize.json +27 -0
  39. data/spec/fixtures/droplet_actions/restore.json +27 -0
  40. data/spec/fixtures/droplet_actions/shutdown.json +27 -0
  41. data/spec/fixtures/droplet_actions/snapshot.json +27 -0
  42. data/spec/fixtures/droplet_actions/upgrade.json +27 -0
  43. data/spec/fixtures/floating_ip_actions/all.json +41 -0
  44. data/spec/fixtures/floating_ip_actions/assign.json +27 -0
  45. data/spec/fixtures/floating_ip_actions/find.json +19 -0
  46. data/spec/fixtures/floating_ip_actions/unassign.json +27 -0
  47. data/spec/fixtures/floating_ips/all.json +186 -0
  48. data/spec/fixtures/floating_ips/all_empty.json +7 -0
  49. data/spec/fixtures/floating_ips/create.json +29 -0
  50. data/spec/fixtures/floating_ips/create_with_droplet.json +44 -0
  51. data/spec/fixtures/floating_ips/find.json +28 -0
  52. data/spec/fixtures/image_actions/convert.json +27 -0
  53. data/spec/fixtures/image_actions/transfer.json +27 -0
  54. data/spec/fixtures/images/private.json +31 -0
  55. data/spec/fixtures/images/type.json +31 -0
  56. data/spec/lib/droplet_kit/resources/account_resource_spec.rb +5 -0
  57. data/spec/lib/droplet_kit/resources/action_resource_spec.rb +7 -0
  58. data/spec/lib/droplet_kit/resources/domain_record_resource_spec.rb +13 -6
  59. data/spec/lib/droplet_kit/resources/domain_resource_spec.rb +10 -3
  60. data/spec/lib/droplet_kit/resources/droplet_action_resource_spec.rb +28 -34
  61. data/spec/lib/droplet_kit/resources/droplet_resource_spec.rb +36 -17
  62. data/spec/lib/droplet_kit/resources/droplet_upgrade_resource_spec.rb +6 -0
  63. data/spec/lib/droplet_kit/resources/floating_ip_action_resource_spec.rb +137 -0
  64. data/spec/lib/droplet_kit/resources/floating_ip_resource_spec.rb +91 -0
  65. data/spec/lib/droplet_kit/resources/image_action_resource_spec.rb +31 -28
  66. data/spec/lib/droplet_kit/resources/image_resource_spec.rb +11 -4
  67. data/spec/lib/droplet_kit/resources/region_resource_spec.rb +6 -0
  68. data/spec/lib/droplet_kit/resources/size_resource_spec.rb +6 -0
  69. data/spec/lib/droplet_kit/resources/ssh_key_resource_spec.rb +7 -0
  70. data/spec/support/request_stub_helpers.rb +1 -1
  71. data/spec/support/shared_examples/common_errors.rb +27 -0
  72. data/spec/support/shared_examples/paginated_endpoint.rb +2 -1
  73. data/spec/support/shared_examples/unsuccessful_create.rb +8 -0
  74. metadata +109 -38
  75. data/spec/support/null_hash_load.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8248d66e3b2a7ea6e7525aa221378fefd3089202
4
- data.tar.gz: 2fc041cce279e282b2775a7dfc183aff9fd3dbb8
3
+ metadata.gz: a8c9257511fd600be1a477ae31232ffa4b3ca0b6
4
+ data.tar.gz: e8879d2fff128825f6c5f9096f7e1ec658b32660
5
5
  SHA512:
6
- metadata.gz: f8546836585fd8f04ed333ab3a66e66e3d7ac9bc34690e09e91323090d9d60c2a908ed968dc3412826177f4b67e72482f51fe190d6d9e31cfceba60ab9c6279b
7
- data.tar.gz: 5b3bbc5443f5119c09bfeca6138f6d0636ea6b193e50cf75011ee6df591ab93cd85621cc34c591e8b651a4a6b690f6e72cb1c434094ea7acd350fd1e71412f88
6
+ metadata.gz: 27af0a122b1a597f1a07145687ca8abb46ccbad633007e524e4fc81137be3d6c6da8ecaa1a6387d733cf776ffc6a399b5ff9788a59780953422947245faff66a
7
+ data.tar.gz: 5a146409578196f9fe891a9253d8fd1652f6259ca815aa5d90de20500807bd400cbc0ee3cfaf9ae2bc4db08242d82ddfcbbf7a912121c77fa8a7edef688864cd
data/README.md CHANGED
@@ -227,7 +227,7 @@ Actions supported:
227
227
 
228
228
  ## Contributing
229
229
 
230
- 1. Fork it ( https://github.com/digitaloceancloud/droplet_kit/fork )
230
+ 1. Fork it ( https://github.com/digitalocean/droplet_kit/fork )
231
231
  2. Create your feature branch (`git checkout -b my-new-feature`)
232
232
  3. Commit your changes (`git commit -am 'Add some feature'`)
233
233
  4. Push to the branch (`git push origin my-new-feature`)
data/droplet_kit.gemspec CHANGED
@@ -21,8 +21,8 @@ Gem::Specification.new do |spec|
21
21
  spec.required_ruby_version = '>= 2.0.0'
22
22
 
23
23
  spec.add_dependency 'virtus', '~> 1.0.3'
24
- spec.add_dependency "resource_kit", '~> 0.1.1'
25
- spec.add_dependency "kartograph", '~> 0.2.1'
24
+ spec.add_dependency "resource_kit", '~> 0.1.4'
25
+ spec.add_dependency "kartograph", '~> 0.2.3'
26
26
  spec.add_dependency "activesupport", '> 3.0', '< 5.0.0'
27
27
  spec.add_dependency "faraday", '~> 0.9.1'
28
28
 
data/lib/droplet_kit.rb CHANGED
@@ -25,6 +25,7 @@ module DropletKit
25
25
  autoload :MetaInformation, 'droplet_kit/models/meta_information'
26
26
  autoload :Account, 'droplet_kit/models/account'
27
27
  autoload :DropletUpgrade, 'droplet_kit/models/droplet_upgrade'
28
+ autoload :FloatingIp, 'droplet_kit/models/floating_ip'
28
29
 
29
30
  # Resources
30
31
  autoload :DropletResource, 'droplet_kit/resources/droplet_resource'
@@ -39,6 +40,8 @@ module DropletKit
39
40
  autoload :SizeResource, 'droplet_kit/resources/size_resource'
40
41
  autoload :AccountResource, 'droplet_kit/resources/account_resource'
41
42
  autoload :DropletUpgradeResource, 'droplet_kit/resources/droplet_upgrade_resource'
43
+ autoload :FloatingIpResource, 'droplet_kit/resources/floating_ip_resource'
44
+ autoload :FloatingIpActionResource, 'droplet_kit/resources/floating_ip_action_resource'
42
45
 
43
46
  # JSON Maps
44
47
  autoload :DropletMapping, 'droplet_kit/mappings/droplet_mapping'
@@ -58,13 +61,27 @@ module DropletKit
58
61
  autoload :SSHKeyMapping, 'droplet_kit/mappings/ssh_key_mapping'
59
62
  autoload :AccountMapping, 'droplet_kit/mappings/account_mapping'
60
63
  autoload :DropletUpgradeMapping, 'droplet_kit/mappings/droplet_upgrade_mapping'
61
-
64
+ autoload :FloatingIpMapping, 'droplet_kit/mappings/floating_ip_mapping'
62
65
 
63
66
  # Utils
64
67
  autoload :PaginatedResource, 'droplet_kit/paginated_resource'
68
+ autoload :ErrorHandlingResourcable, 'droplet_kit/error_handling_resourcable'
65
69
 
66
70
  # Errors
67
71
  autoload :ErrorMapping, 'droplet_kit/mappings/error_mapping'
68
- FailedCreate = Class.new(StandardError)
69
- FailedUpdate = Class.new(StandardError)
72
+ Error = Class.new(StandardError)
73
+ FailedCreate = Class.new(DropletKit::Error)
74
+ FailedUpdate = Class.new(DropletKit::Error)
75
+
76
+ class RateLimitReached < DropletKit::Error
77
+ attr_accessor :limit, :remaining, :reset_at
78
+
79
+ def limit
80
+ @limit.to_i if @limit
81
+ end
82
+
83
+ def remaining
84
+ @remaining.to_i if @remaining
85
+ end
86
+ end
70
87
  end
@@ -29,6 +29,8 @@ module DropletKit
29
29
  sizes: SizeResource,
30
30
  ssh_keys: SSHKeyResource,
31
31
  account: AccountResource,
32
+ floating_ips: FloatingIpResource,
33
+ floating_ip_actions: FloatingIpActionResource,
32
34
  }
33
35
  end
34
36
 
@@ -0,0 +1,19 @@
1
+ module ErrorHandlingResourcable
2
+ def self.included(base)
3
+ base.send(:resources) do
4
+ default_handler do |response|
5
+ if (200...299).include?(response.status)
6
+ next
7
+ elsif response.status == 429
8
+ error = DropletKit::RateLimitReached.new("#{response.status}: #{response.body}")
9
+ error.limit = response.headers['RateLimit-Limit']
10
+ error.remaining = response.headers['RateLimit-Remaining']
11
+ error.reset_at = response.headers['RateLimit-Reset']
12
+ raise error
13
+ else
14
+ raise DropletKit::Error.new("#{response.status}: #{response.body}")
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -7,12 +7,12 @@ module DropletKit
7
7
  root_key plural: 'domain_records', singular: 'domain_record', scopes: [:read]
8
8
 
9
9
  property :id, scopes: [:read]
10
- property :type, scopes: [:read, :create]
10
+ property :type, scopes: [:read, :create, :update]
11
11
  property :name, scopes: [:read, :create, :update]
12
- property :data, scopes: [:read, :create]
13
- property :priority, scopes: [:read, :create]
14
- property :port, scopes: [:read, :create]
15
- property :weight, scopes: [:read, :create]
12
+ property :data, scopes: [:read, :create, :update]
13
+ property :priority, scopes: [:read, :create, :update]
14
+ property :port, scopes: [:read, :create, :update]
15
+ property :weight, scopes: [:read, :create, :update]
16
16
  end
17
17
  end
18
- end
18
+ end
@@ -0,0 +1,19 @@
1
+ module DropletKit
2
+ class FloatingIpMapping
3
+ include Kartograph::DSL
4
+
5
+ kartograph do
6
+ mapping FloatingIp
7
+ root_key plural: 'floating_ips', singular: 'floating_ip', scopes: [:read]
8
+
9
+ property :ip, scopes: [:read]
10
+
11
+ property :region, scopes: [:read], include: RegionMapping
12
+ property :droplet, scopes: [:read], include: DropletMapping
13
+
14
+ # Create properties aren't quite the same
15
+ property :droplet_id, scopes: [:create]
16
+ property :region, scopes: [:create]
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ module DropletKit
2
+ class FloatingIp < BaseModel
3
+ attribute :ip
4
+ attribute :region
5
+ attribute :droplet
6
+
7
+ # Used for creates
8
+ attribute :droplet_id
9
+ end
10
+ end
@@ -45,7 +45,7 @@ module DropletKit
45
45
 
46
46
  def total_pages
47
47
  return nil if self.total.nil?
48
-
48
+
49
49
  (self.total.to_f / per_page.to_f).ceil
50
50
  end
51
51
 
@@ -1,5 +1,7 @@
1
1
  module DropletKit
2
2
  class AccountResource < ResourceKit::Resource
3
+ include ErrorHandlingResourcable
4
+
3
5
  resources do
4
6
  default_handler(:ok) {|r| AccountMapping.extract_single(r.body, :read) }
5
7
  get '/v2/account' => :info
@@ -1,5 +1,7 @@
1
1
  module DropletKit
2
2
  class ActionResource < ResourceKit::Resource
3
+ include ErrorHandlingResourcable
4
+
3
5
  resources do
4
6
  action :all, 'GET /v2/actions' do
5
7
  query_keys :per_page, :page
@@ -1,5 +1,7 @@
1
1
  module DropletKit
2
2
  class DomainRecordResource < ResourceKit::Resource
3
+ include ErrorHandlingResourcable
4
+
3
5
  resources do
4
6
  action :all, 'GET /v2/domains/:for_domain/records' do
5
7
  query_keys :per_page, :page
@@ -1,5 +1,7 @@
1
1
  module DropletKit
2
2
  class DomainResource < ResourceKit::Resource
3
+ include ErrorHandlingResourcable
4
+
3
5
  resources do
4
6
  action :all, 'GET /v2/domains' do
5
7
  query_keys :per_page, :page
@@ -1,9 +1,13 @@
1
1
  module DropletKit
2
2
  class DropletActionResource < ResourceKit::Resource
3
+ include ErrorHandlingResourcable
4
+
3
5
  ACTIONS_WITHOUT_INPUT = %w(reboot power_cycle shutdown power_off
4
6
  power_on password_reset enable_ipv6 disable_backups enable_private_networking)
5
7
 
6
8
  resources do
9
+ default_handler(422) { |response| ErrorMapping.fail_with(FailedCreate, response.body) }
10
+
7
11
  ACTIONS_WITHOUT_INPUT.each do |action_name|
8
12
  action action_name.to_sym, 'POST /v2/droplets/:droplet_id/actions' do
9
13
  body { |_| { type: action_name }.to_json }
@@ -1,5 +1,7 @@
1
1
  module DropletKit
2
2
  class DropletResource < ResourceKit::Resource
3
+ include ErrorHandlingResourcable
4
+
3
5
  resources do
4
6
  action :all, 'GET /v2/droplets' do
5
7
  query_keys :per_page, :page
@@ -12,7 +14,7 @@ module DropletKit
12
14
 
13
15
  action :create, 'POST /v2/droplets' do
14
16
  body { |object| DropletMapping.representation_for(:create, object) }
15
- handler(202) { |response| DropletMapping.extract_single(response.body, :read) }
17
+ handler(202) { |response, droplet| DropletMapping.extract_into_object(droplet, response.body, :read) }
16
18
  handler(422) { |response| ErrorMapping.fail_with(FailedCreate, response.body) }
17
19
  end
18
20
 
@@ -1,5 +1,7 @@
1
1
  module DropletKit
2
2
  class DropletUpgradeResource < ResourceKit::Resource
3
+ include ErrorHandlingResourcable
4
+
3
5
  resources do
4
6
  action :all, 'GET /v2/droplet_upgrades' do
5
7
  handler(200) { |response| DropletUpgradeMapping.extract_collection(response.body, :read) }
@@ -0,0 +1,30 @@
1
+ module DropletKit
2
+ class FloatingIpActionResource < ResourceKit::Resource
3
+ resources do
4
+ default_handler(422) { |response| ErrorMapping.fail_with(FailedCreate, response.body) }
5
+
6
+ action :assign, 'POST /v2/floating_ips/:ip/actions' do
7
+ body { |hash| { type: 'assign', droplet_id: hash[:droplet_id] }.to_json }
8
+ handler(201, 200) { |response| ActionMapping.extract_single(response.body, :read) }
9
+ end
10
+
11
+ action :unassign, 'POST /v2/floating_ips/:ip/actions' do
12
+ body { |hash| { type: 'unassign' }.to_json }
13
+ handler(201, 200) { |response| ActionMapping.extract_single(response.body, :read) }
14
+ end
15
+
16
+ action :find, 'GET /v2/floating_ips/:ip/actions/:id' do
17
+ handler(200) { |response| ActionMapping.extract_single(response.body, :read) }
18
+ end
19
+
20
+ action :all, 'GET /v2/floating_ips/:ip/actions' do
21
+ query_keys :per_page, :page
22
+ handler(200) { |response| ActionMapping.extract_collection(response.body, :read) }
23
+ end
24
+ end
25
+
26
+ def all(*args)
27
+ PaginatedResource.new(action(:all), self, *args)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,29 @@
1
+ module DropletKit
2
+ class FloatingIpResource < ResourceKit::Resource
3
+ resources do
4
+ action :all, 'GET /v2/floating_ips' do
5
+ query_keys :per_page, :page
6
+ handler(200) { |response| FloatingIpMapping.extract_collection(response.body, :read) }
7
+ end
8
+
9
+ action :find, 'GET /v2/floating_ips/:ip' do
10
+ handler(200) { |response| FloatingIpMapping.extract_single(response.body, :read) }
11
+ end
12
+
13
+ action :create, 'POST /v2/floating_ips' do
14
+ body { |object| FloatingIpMapping.representation_for(:create, object) }
15
+ handler(202) { |response| FloatingIpMapping.extract_single(response.body, :read) }
16
+ handler(422) { |response| ErrorMapping.fail_with(FailedCreate, response.body) }
17
+ end
18
+
19
+ action :delete, 'DELETE /v2/floating_ips/:ip' do
20
+ handler(202) { |response| ActionMapping.extract_single(response.body, :read) }
21
+ handler(204) { |response| true }
22
+ end
23
+ end
24
+
25
+ def all(*args)
26
+ PaginatedResource.new(action(:all), self, *args)
27
+ end
28
+ end
29
+ end
@@ -1,6 +1,10 @@
1
1
  module DropletKit
2
2
  class ImageActionResource < ResourceKit::Resource
3
+ include ErrorHandlingResourcable
4
+
3
5
  resources do
6
+ default_handler(422) { |response| ErrorMapping.fail_with(FailedCreate, response.body) }
7
+
4
8
  action :transfer, 'POST /v2/images/:image_id/actions' do
5
9
  body { |object| { type: 'transfer', region: object[:region] }.to_json }
6
10
  handler(200, 201) { |response| ImageActionMapping.extract_single(response.body, :read) }
@@ -1,5 +1,7 @@
1
1
  module DropletKit
2
2
  class ImageResource < ResourceKit::Resource
3
+ include ErrorHandlingResourcable
4
+
3
5
  resources do
4
6
  action :all, 'GET /v2/images' do
5
7
  query_keys :page, :per_page, :type, :private
@@ -1,5 +1,7 @@
1
1
  module DropletKit
2
2
  class RegionResource < ResourceKit::Resource
3
+ include ErrorHandlingResourcable
4
+
3
5
  resources do
4
6
  action :all, 'GET /v2/regions' do
5
7
  query_keys :per_page, :page
@@ -1,5 +1,7 @@
1
1
  module DropletKit
2
2
  class SizeResource < ResourceKit::Resource
3
+ include ErrorHandlingResourcable
4
+
3
5
  resources do
4
6
  action :all, 'GET /v2/sizes' do
5
7
  query_keys :per_page, :page
@@ -1,5 +1,7 @@
1
1
  module DropletKit
2
2
  class SSHKeyResource < ResourceKit::Resource
3
+ include ErrorHandlingResourcable
4
+
3
5
  resources do
4
6
  default_handler(:ok, :created) {|r| SSHKeyMapping.extract_single(r.body, :read) }
5
7
 
@@ -1,3 +1,3 @@
1
1
  module DropletKit
2
- VERSION = "1.2.3"
2
+ VERSION = "1.3.0"
3
3
  end
@@ -0,0 +1,27 @@
1
+ {
2
+ "action": {
3
+ "id": 2,
4
+ "status": "in-progress",
5
+ "type": "change_kernel",
6
+ "started_at": "2014-07-29T14:35:27Z",
7
+ "completed_at": null,
8
+ "resource_id": 12,
9
+ "resource_type": "droplet",
10
+ "region_slug": "nyc1",
11
+ "region": {
12
+ "name": "New York",
13
+ "slug": "nyc1",
14
+ "available": true,
15
+ "sizes": [
16
+ "512mb"
17
+ ],
18
+ "features": [
19
+ "virtio",
20
+ "private_networking",
21
+ "backups",
22
+ "ipv6",
23
+ "metadata"
24
+ ]
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "action": {
3
+ "id": 2,
4
+ "status": "in-progress",
5
+ "type": "disable_backups",
6
+ "started_at": "2014-07-29T14:35:27Z",
7
+ "completed_at": null,
8
+ "resource_id": 12,
9
+ "resource_type": "droplet",
10
+ "region_slug": "nyc1",
11
+ "region": {
12
+ "name": "New York",
13
+ "slug": "nyc1",
14
+ "available": true,
15
+ "sizes": [
16
+ "512mb"
17
+ ],
18
+ "features": [
19
+ "virtio",
20
+ "private_networking",
21
+ "backups",
22
+ "ipv6",
23
+ "metadata"
24
+ ]
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "action": {
3
+ "id": 2,
4
+ "status": "in-progress",
5
+ "type": "enable_ipv6",
6
+ "started_at": "2014-07-29T14:35:27Z",
7
+ "completed_at": null,
8
+ "resource_id": 12,
9
+ "resource_type": "droplet",
10
+ "region_slug": "nyc1",
11
+ "region": {
12
+ "name": "New York",
13
+ "slug": "nyc1",
14
+ "available": true,
15
+ "sizes": [
16
+ "512mb"
17
+ ],
18
+ "features": [
19
+ "virtio",
20
+ "private_networking",
21
+ "backups",
22
+ "ipv6",
23
+ "metadata"
24
+ ]
25
+ }
26
+ }
27
+ }