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 +4 -4
- data/README.md +40 -3
- data/lib/droplet_kit/client.rb +32 -7
- 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/vpc_peering_mapping.rb +29 -0
- data/lib/droplet_kit/models/account.rb +7 -0
- data/lib/droplet_kit/models/vpc_peering.rb +11 -0
- data/lib/droplet_kit/resources/droplet_action_resource.rb +1 -1
- data/lib/droplet_kit/resources/vpc_peering_resource.rb +43 -0
- data/lib/droplet_kit/version.rb +1 -1
- data/lib/droplet_kit.rb +3 -0
- metadata +33 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 615cc2a41f53e00443e4a8b59ea4e1af6b2f8edaf56c35fb764e79b5b28b77f3
|
4
|
+
data.tar.gz: 949eb311f59b8923be9c91864482fde4cbf836869c62a095a5aafde54a161bdf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
# =>
|
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')`
|
@@ -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')
|
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
|
|
@@ -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
|
-
|
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
|
@@ -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
|
@@ -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"
|
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
|
data/lib/droplet_kit/version.rb
CHANGED
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.
|
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:
|
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
|