droplet_kit 1.2.3 → 1.3.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.
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
+ }