droplet_kit 3.19.0 → 3.21.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a7aa72baa7a9ea4de7fccdc3953c36aec28083aef5339779376e12306b93b09e
4
- data.tar.gz: d539ac1f1fab8846796194ca7f125343ce4749638a277f2d8f3b39afdffc100d
3
+ metadata.gz: 615cc2a41f53e00443e4a8b59ea4e1af6b2f8edaf56c35fb764e79b5b28b77f3
4
+ data.tar.gz: 949eb311f59b8923be9c91864482fde4cbf836869c62a095a5aafde54a161bdf
5
5
  SHA512:
6
- metadata.gz: dfb0481753a0c360839768dc31c4f1b4b6214e24f7ef9a7ed2d0882f973ce90288a47c5f61cc0ae36f3df43badb80e69ac5b918de21a408726a070e35cceceae
7
- data.tar.gz: 0a353b970b108ccb455ad87d17f20b63847a44b703fb8e1fa9ea0dabb139c5d5f86c9c4c0e02c312f3344f8fb170541528441480b85fa93781be0d3d6be8efbc
6
+ metadata.gz: c78d6a1b8b99b43bceb14fe12a6a07aef9d5ca08e6ae6724897082d6b619ae393d0a4332018f05682851bfa89a13247fa97fc58d594b32f76d8518e857c9fa22
7
+ data.tar.gz: 813777d5eaa8e768291b2b4a0d9c74da033db81ce02f905227afea51283b25108b62a14d08fad46241c4db3677eec94199a9cb2926f5141c8e9ba9cb5fe9f6e7
data/README.md CHANGED
@@ -52,6 +52,19 @@ require 'droplet_kit'
52
52
  client = DropletKit::Client.new(access_token: 'YOUR_TOKEN', user_agent: 'custom')
53
53
  ```
54
54
 
55
+ ### Automatically Retry Rate Limited Requests
56
+
57
+ By default, DropletKit will handle requests that are rate limited by the DigitalOcean API's [burst limit](https://docs.digitalocean.com/reference/api/api-reference/#section/Introduction/Rate-Limit). When the burst rate limit is reached, DropletKit will wait according to the value of the API response's `Retry-After` header. Typically the wait time is less than one minute. When the hourly rate limit is hit, an error is raised.
58
+
59
+ By default, DropletKit will retry a rate limited request three times before returning an error. If you would like to disable the retry behavior altogether, and instead raise an error when any rate limit is reached, you can set the `retry_max` config value to zero.
60
+
61
+ DropletKit will also wait zero seconds until retrying a request after the `Retry-After` time has elapsed by default. To change this, set the `retry_wait_min` to a different value.
62
+
63
+ ```ruby
64
+ require 'droplet_kit'
65
+ client = DropletKit::Client.new(access_token: 'YOUR_TOKEN', retry_max: 3, retry_wait_min: 1)
66
+ ```
67
+
55
68
  ## Design
56
69
 
57
70
  DropletKit follows a strict design of resources as methods on your client. For examples, for droplets, you will call your client like this:
@@ -61,12 +74,22 @@ client = DropletKit::Client.new(access_token: 'YOUR_TOKEN')
61
74
  client.droplets #=> DropletsResource
62
75
  ```
63
76
 
64
- DropletKit will return Plain Old Ruby objects(tm) that contain the information provided by the API. For example:
77
+ DropletKit will return Plain Old Ruby objects(tm) that contain the information provided by the API. For actions that return multiple objects, the request won't be executed until the result is accessed. For example:
65
78
 
66
79
  ```ruby
67
80
  client = DropletKit::Client.new(access_token: 'YOUR_TOKEN')
81
+
82
+ # Returns an instance of a Paginated Resource.
68
83
  client.droplets.all
69
- # => [ DropletKit::Droplet(id: 123, name: 'something.com', ...), DropletKit::Droplet(id: 1066, name: 'bunk.com', ...) ]
84
+ # => #<DropletKit::PaginatedResource:0x000000010d556c3a>
85
+
86
+ # Returns the first Droplet.
87
+ client.droplets.all.first
88
+ # => <DropletKit::Droplet {:@id=>1, :@name=>"mydroplet", ...}>
89
+
90
+ # Returns an array of Droplet IDs.
91
+ client.droplets.all.map(&:id)
92
+ # => [1]
70
93
  ```
71
94
 
72
95
  When you'd like to save objects, it's your responsibility to instantiate the objects and persist them using the resource objects. Let's use creating a Droplet as an example:
@@ -153,7 +176,7 @@ Actions supported:
153
176
  * `client.databases.list_backups(id: 'id')`
154
177
  * `client.databases.restore_from_backup(database_backup)`
155
178
  * `client.databases.delete_cluster(id: 'id')`
156
- * `client.database.create_db(database, id: 'id')`
179
+ * `client.databases.create_db(database, id: 'id')`
157
180
  * `client.databases.find_db(id: 'id', name: 'name')`
158
181
  * `client.databases.all_dbs(id: 'id')`
159
182
  * `client.databases.delete_db(id: 'id', name: 'name')`
@@ -599,6 +622,20 @@ Actions supported:
599
622
  * `client.vpcs.delete(id: 'id')`
600
623
  * `client.vpcs.all_members(id: 'id')`
601
624
 
625
+ ## VPC Peering resource
626
+
627
+ client = DropletKit::Client.new(access_token: 'TOKEN')
628
+ client.vpc_peerings #=> DropletKit::VPCPeeringResource
629
+
630
+ Actions supported:
631
+
632
+ * `client.vpc_peerings.find(id: 'id')`
633
+ * `client.vpc_peerings.all()`
634
+ * `client.vpc_peerings.create(vpc_peering)`
635
+ * `client.vpc_peerings.update(vpc_peering, id: 'id')`
636
+ * `client.vpc_peerings.patch(vpc_peering, id: 'id')`
637
+ * `client.vpc_peerings.delete(id: 'id')`
638
+
602
639
  ## Container Registry resource
603
640
 
604
641
  client = DropletKit::Client.new(access_token: 'TOKEN')
@@ -1,23 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'faraday'
4
+ require 'faraday/retry'
4
5
  require 'droplet_kit/utils'
5
6
 
6
7
  module DropletKit
7
8
  class Client
8
9
  DEFAULT_OPEN_TIMEOUT = 60
9
10
  DEFAULT_TIMEOUT = 120
11
+ DEFAULT_RETRY_MAX = 3
12
+ DEFAULT_RETRY_WAIT_MIN = 0
13
+
10
14
  DIGITALOCEAN_API = 'https://api.digitalocean.com'
11
15
 
12
- attr_reader :access_token, :api_url, :open_timeout, :timeout, :user_agent
16
+ attr_reader :access_token, :api_url, :open_timeout, :timeout, :user_agent, :retry_max, :retry_wait_min
13
17
 
14
18
  def initialize(options = {})
15
19
  options = DropletKit::Utils.transform_keys(options, &:to_sym)
16
- @access_token = options[:access_token]
17
- @api_url = options[:api_url] || DIGITALOCEAN_API
18
- @open_timeout = options[:open_timeout] || DEFAULT_OPEN_TIMEOUT
19
- @timeout = options[:timeout] || DEFAULT_TIMEOUT
20
- @user_agent = options[:user_agent]
20
+ @access_token = options[:access_token]
21
+ @api_url = options[:api_url] || DIGITALOCEAN_API
22
+ @open_timeout = options[:open_timeout] || DEFAULT_OPEN_TIMEOUT
23
+ @timeout = options[:timeout] || DEFAULT_TIMEOUT
24
+ @user_agent = options[:user_agent]
25
+ @retry_max = options[:retry_max] || DEFAULT_RETRY_MAX
26
+ @retry_wait_min = options[:retry_wait_min] || DEFAULT_RETRY_WAIT_MIN
21
27
  end
22
28
 
23
29
  def connection
@@ -25,6 +31,19 @@ module DropletKit
25
31
  req.adapter :net_http
26
32
  req.options.open_timeout = open_timeout
27
33
  req.options.timeout = timeout
34
+ unless retry_max.zero?
35
+ req.request :retry, {
36
+ max: @retry_max,
37
+ interval: @retry_wait_min,
38
+ retry_statuses: [429],
39
+ # faraday-retry supports both the Retry-After and RateLimit-Reset
40
+ # headers, however, it favours the RateLimit-Reset one. To force it
41
+ # to use the Retry-After header, we override the header that it
42
+ # expects for the RateLimit-Reset header to something that we know
43
+ # we don't set.
44
+ rate_limit_reset_header: 'undefined'
45
+ }
46
+ end
28
47
  end
29
48
  end
30
49
 
@@ -61,7 +80,8 @@ module DropletKit
61
80
  projects: ProjectResource,
62
81
  volumes: VolumeResource,
63
82
  volume_actions: VolumeActionResource,
64
- vpcs: VPCResource
83
+ vpcs: VPCResource,
84
+ vpc_peerings: VPCPeeringResource
65
85
  }
66
86
  end
67
87
 
@@ -91,6 +111,11 @@ module DropletKit
91
111
  content_type: 'application/json',
92
112
  authorization: "Bearer #{access_token}",
93
113
  user_agent: "#{user_agent} #{default_user_agent}".strip
114
+ },
115
+ request: {
116
+ context: {
117
+ retry_max: @retry_max
118
+ }
94
119
  }
95
120
  }
96
121
  end
@@ -8,11 +8,13 @@ module ErrorHandlingResourcable
8
8
  when 200...299
9
9
  next
10
10
  when 429
11
- error = DropletKit::RateLimitReached.new("#{response.status}: #{response.body}")
12
- error.limit = response.headers['RateLimit-Limit']
13
- error.remaining = response.headers['RateLimit-Remaining']
14
- error.reset_at = response.headers['RateLimit-Reset']
15
- raise error
11
+ unless response.headers.key?('Retry-After') && !connection.options.context.key?(:retry_max)
12
+ error = DropletKit::RateLimitReached.new("#{response.status}: #{response.body}")
13
+ error.limit = response.headers['RateLimit-Limit']
14
+ error.remaining = response.headers['RateLimit-Remaining']
15
+ error.reset_at = response.headers['RateLimit-Reset']
16
+ raise error
17
+ end
16
18
  else
17
19
  raise DropletKit::Error, "#{response.status}: #{response.body}"
18
20
  end
@@ -11,9 +11,25 @@ module DropletKit
11
11
  scoped :read do
12
12
  property :droplet_limit
13
13
  property :floating_ip_limit
14
+ property :name
14
15
  property :email
15
16
  property :uuid
16
17
  property :email_verified
18
+ property :team
19
+ end
20
+ end
21
+ end
22
+
23
+ class AccountTeamMapping
24
+ include Kartograph::DSL
25
+
26
+ kartograph do
27
+ root_key singular: 'team', scopes: [:read]
28
+ mapping AccountTeam
29
+
30
+ scoped :read do
31
+ property :uuid
32
+ property :name
17
33
  end
18
34
  end
19
35
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DropletKit
4
+ class VPCPeeringMapping
5
+ include Kartograph::DSL
6
+
7
+ kartograph do
8
+ mapping VPCPeering
9
+ root_key plural: 'vpc_peerings', singular: 'vpc_peering', scopes: [:read]
10
+
11
+ scoped :read do
12
+ property :id
13
+ property :name
14
+ property :vpc_ids
15
+ property :created_at
16
+ property :status
17
+ end
18
+
19
+ scoped :update, :patch do
20
+ property :name
21
+ end
22
+
23
+ scoped :create do
24
+ property :name
25
+ property :vpc_ids
26
+ end
27
+ end
28
+ end
29
+ end
@@ -4,8 +4,15 @@ module DropletKit
4
4
  class Account < BaseModel
5
5
  attribute :droplet_limit
6
6
  attribute :floating_ip_limit
7
+ attribute :name
7
8
  attribute :email
8
9
  attribute :uuid
9
10
  attribute :email_verified
11
+ attribute :team
12
+ end
13
+
14
+ class AccountTeam < BaseModel
15
+ attribute :uuid
16
+ attribute :name
10
17
  end
11
18
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DropletKit
4
+ class VPCPeering < BaseModel
5
+ attribute :id
6
+ attribute :name
7
+ attribute :vpc_ids
8
+ attribute :created_at
9
+ attribute :status
10
+ end
11
+ end
@@ -35,7 +35,7 @@ module DropletKit
35
35
  end
36
36
 
37
37
  TAG_ACTIONS.each do |action_name|
38
- action "#{action_name}_for_tag".to_sym, 'POST /v2/droplets/actions' do
38
+ action :"#{action_name}_for_tag", 'POST /v2/droplets/actions' do
39
39
  query_keys :tag_name
40
40
  body { |_| { type: action_name }.to_json }
41
41
  handler(201, 200) { |response| ActionMapping.extract_collection(response.body, :read) }
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DropletKit
4
+ class VPCPeeringResource < ResourceKit::Resource
5
+ include ErrorHandlingResourcable
6
+
7
+ resources do
8
+ action :find, 'GET /v2/vpc_peerings/:id' do
9
+ handler(200) do |response|
10
+ VPCPeeringMapping.extract_single(response.body, :read)
11
+ end
12
+ end
13
+
14
+ action :all, 'GET /v2/vpc_peerings' do
15
+ query_keys :per_page, :page
16
+
17
+ handler(200) do |response|
18
+ VPCPeeringMapping.extract_collection(response.body, :read)
19
+ end
20
+ end
21
+
22
+ action :create, 'POST /v2/vpc_peerings' do
23
+ body { |vpc_peering| VPCPeeringMapping.representation_for(:create, vpc_peering) }
24
+ handler(202) { |response| VPCPeeringMapping.extract_single(response.body, :read) }
25
+ handler(422) { |response| ErrorMapping.fail_with(FailedCreate, response.body) }
26
+ end
27
+
28
+ action :patch, 'PATCH /v2/vpc_peerings/:id' do
29
+ body { |vpc_peering| VPCPeeringMapping.representation_for(:patch, vpc_peering) }
30
+ handler(200) { |response| VPCPeeringMapping.extract_single(response.body, :read) }
31
+ handler(422) { |response| ErrorMapping.fail_with(FailedUpdate, response.body) }
32
+ end
33
+
34
+ action :delete, 'DELETE /v2/vpc_peerings/:id' do
35
+ handler(202) { |response| VPCPeeringMapping.extract_single(response.body, :read) }
36
+ end
37
+ end
38
+
39
+ def all(*args)
40
+ PaginatedResource.new(action(:all), self, *args)
41
+ end
42
+ end
43
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DropletKit
4
- VERSION = '3.19.0'
4
+ VERSION = '3.21.0'
5
5
  end
data/lib/droplet_kit.rb CHANGED
@@ -69,6 +69,7 @@ module DropletKit
69
69
  autoload :KubernetesOptions, 'droplet_kit/models/kubernetes_options'
70
70
  autoload :VPC, 'droplet_kit/models/vpc'
71
71
  autoload :VPCMember, 'droplet_kit/models/vpc_member'
72
+ autoload :VPCPeering, 'droplet_kit/models/vpc_peering'
72
73
 
73
74
  # Resources
74
75
  autoload :DropletResource, 'droplet_kit/resources/droplet_resource'
@@ -104,6 +105,7 @@ module DropletKit
104
105
  autoload :KubernetesClusterResource, 'droplet_kit/resources/kubernetes_cluster_resource'
105
106
  autoload :KubernetesOptionsResource, 'droplet_kit/resources/kubernetes_options_resource'
106
107
  autoload :VPCResource, 'droplet_kit/resources/vpc_resource'
108
+ autoload :VPCPeeringResource, 'droplet_kit/resources/vpc_peering_resource'
107
109
 
108
110
  # JSON Maps
109
111
  autoload :DropletMapping, 'droplet_kit/mappings/droplet_mapping'
@@ -168,6 +170,7 @@ module DropletKit
168
170
  autoload :KubernetesOptionsMapping, 'droplet_kit/mappings/kubernetes_options_mapping'
169
171
  autoload :VPCMapping, 'droplet_kit/mappings/vpc_mapping'
170
172
  autoload :VPCMemberMapping, 'droplet_kit/mappings/vpc_member_mapping'
173
+ autoload :VPCPeeringMapping, 'droplet_kit/mappings/vpc_peering_mapping'
171
174
 
172
175
  # Utils
173
176
  autoload :PaginatedResource, 'droplet_kit/paginated_resource'
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: droplet_kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.19.0
4
+ version: 3.21.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - DigitalOcean API Engineering team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-03 00:00:00.000000000 Z
11
+ date: 2024-05-17 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bigdecimal
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: faraday
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -24,6 +38,20 @@ dependencies:
24
38
  - - ">="
25
39
  - !ruby/object:Gem::Version
26
40
  version: '0.15'
41
+ - !ruby/object:Gem::Dependency
42
+ name: faraday-retry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 2.2.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 2.2.0
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: kartograph
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -285,6 +313,7 @@ files:
285
313
  - lib/droplet_kit/mappings/volume_mapping.rb
286
314
  - lib/droplet_kit/mappings/vpc_mapping.rb
287
315
  - lib/droplet_kit/mappings/vpc_member_mapping.rb
316
+ - lib/droplet_kit/mappings/vpc_peering_mapping.rb
288
317
  - lib/droplet_kit/models/account.rb
289
318
  - lib/droplet_kit/models/action.rb
290
319
  - lib/droplet_kit/models/balance.rb
@@ -348,6 +377,7 @@ files:
348
377
  - lib/droplet_kit/models/volume.rb
349
378
  - lib/droplet_kit/models/vpc.rb
350
379
  - lib/droplet_kit/models/vpc_member.rb
380
+ - lib/droplet_kit/models/vpc_peering.rb
351
381
  - lib/droplet_kit/paginated_resource.rb
352
382
  - lib/droplet_kit/resources/account_resource.rb
353
383
  - lib/droplet_kit/resources/action_resource.rb
@@ -381,6 +411,7 @@ files:
381
411
  - lib/droplet_kit/resources/tag_resource.rb
382
412
  - lib/droplet_kit/resources/volume_action_resource.rb
383
413
  - lib/droplet_kit/resources/volume_resource.rb
414
+ - lib/droplet_kit/resources/vpc_peering_resource.rb
384
415
  - lib/droplet_kit/resources/vpc_resource.rb
385
416
  - lib/droplet_kit/utils.rb
386
417
  - lib/droplet_kit/version.rb