droplet_kit 3.18.0 → 3.20.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +26 -3
- data/lib/droplet_kit/client.rb +30 -6
- data/lib/droplet_kit/error_handling_resourcable.rb +7 -5
- data/lib/droplet_kit/mappings/account_mapping.rb +16 -0
- data/lib/droplet_kit/mappings/droplet_mapping.rb +1 -0
- data/lib/droplet_kit/models/account.rb +7 -0
- data/lib/droplet_kit/version.rb +1 -1
- data/lib/tasks/resource_doc.rake +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4fc38c8c6d69e9d358d6a5ce09f48d81f86162b21353864d111362d73ad869d0
|
4
|
+
data.tar.gz: 69924df50fd90082ab18b00ff46678625bf199929bf722a43a60bb6bd4d4bcc2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a119768dc94088edf60b0e33fa7429496686d9494350204531b019c491fc8413ff8364cca381495646e3d72c36d39827906e06a0eac8e4eae69faaa9c2a47972
|
7
|
+
data.tar.gz: abd960f172d61201e42e126cf34a298d4da149f8e0b4cdc2fa19fc96c8b1666b96e81c9a0f612f8aa0cf5ee41ea78d9d304902ab3330084d33a41ecd5c6c91aa
|
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
|
-
# =>
|
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.
|
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')`
|
data/lib/droplet_kit/client.rb
CHANGED
@@ -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
|
17
|
-
@api_url
|
18
|
-
@open_timeout
|
19
|
-
@timeout
|
20
|
-
@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
|
|
@@ -91,6 +110,11 @@ module DropletKit
|
|
91
110
|
content_type: 'application/json',
|
92
111
|
authorization: "Bearer #{access_token}",
|
93
112
|
user_agent: "#{user_agent} #{default_user_agent}".strip
|
113
|
+
},
|
114
|
+
request: {
|
115
|
+
context: {
|
116
|
+
retry_max: @retry_max
|
117
|
+
}
|
94
118
|
}
|
95
119
|
}
|
96
120
|
end
|
@@ -8,11 +8,13 @@ module ErrorHandlingResourcable
|
|
8
8
|
when 200...299
|
9
9
|
next
|
10
10
|
when 429
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
@@ -24,6 +24,7 @@ module DropletKit
|
|
24
24
|
property :tags, scopes: [:read]
|
25
25
|
property :vpc_uuid, scopes: [:read]
|
26
26
|
property :volume_ids, scopes: [:read]
|
27
|
+
property :size, scopes: [:read], include: SizeMapping
|
27
28
|
|
28
29
|
property :region, scopes: [:read], include: RegionMapping
|
29
30
|
property :image, scopes: [:read], include: ImageMapping
|
@@ -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
|
data/lib/droplet_kit/version.rb
CHANGED
data/lib/tasks/resource_doc.rake
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: droplet_kit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.20.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:
|
11
|
+
date: 2023-08-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0.15'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday-retry
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.2.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.2.0
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: kartograph
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|