wavefront-sdk 3.7.0 → 5.1.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +43 -2
- data/.travis.yml +0 -1
- data/HISTORY.md +32 -0
- data/README.md +4 -3
- data/lib/wavefront-sdk/account.rb +104 -3
- data/lib/wavefront-sdk/api_mixins/user.rb +10 -0
- data/lib/wavefront-sdk/cloudintegration.rb +27 -0
- data/lib/wavefront-sdk/core/api_caller.rb +50 -7
- data/lib/wavefront-sdk/core/exception.rb +5 -0
- data/lib/wavefront-sdk/defs/version.rb +1 -3
- data/lib/wavefront-sdk/paginator/base.rb +21 -15
- data/lib/wavefront-sdk/query.rb +0 -1
- data/lib/wavefront-sdk/role.rb +128 -0
- data/lib/wavefront-sdk/spy.rb +126 -0
- data/lib/wavefront-sdk/stdlib/array.rb +1 -1
- data/lib/wavefront-sdk/stdlib/time.rb +13 -0
- data/lib/wavefront-sdk/unstable/README.md +4 -0
- data/lib/wavefront-sdk/unstable/chart.rb +90 -0
- data/lib/wavefront-sdk/unstable/unstable.rb +9 -0
- data/lib/wavefront-sdk/user.rb +31 -0
- data/lib/wavefront-sdk/usergroup.rb +17 -16
- data/lib/wavefront-sdk/validators.rb +52 -7
- data/lib/wavefront-sdk/write.rb +13 -3
- data/spec/.rubocop.yml +41 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/support/minitest_assertions.rb +4 -4
- data/spec/wavefront-sdk/account_spec.rb +107 -1
- data/spec/wavefront-sdk/cloudintegration_spec.rb +38 -0
- data/spec/wavefront-sdk/core/api_caller_spec.rb +43 -0
- data/spec/wavefront-sdk/metric_helper_spec.rb +1 -1
- data/spec/wavefront-sdk/role_spec.rb +96 -0
- data/spec/wavefront-sdk/spy_spec.rb +113 -0
- data/spec/wavefront-sdk/unstable/chart_spec.rb +39 -0
- data/spec/wavefront-sdk/user_spec.rb +8 -0
- data/spec/wavefront-sdk/usergroup_spec.rb +21 -11
- data/spec/wavefront-sdk/validators_spec.rb +31 -0
- data/wavefront-sdk.gemspec +4 -4
- metadata +24 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6fa47f9b8dc9c71f547e50131d53cfcdf5ae0142cd75f14558afd5303576a4cc
|
4
|
+
data.tar.gz: '08bea64a048f8e22e02c4b8b12fa6e413a9e26bbb1e5c55e26201ac873424812'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea55156acfeaadce57ff846aa723c936c77f061730ef7f1e91b2b2919c51dfa2cc1b0652d1485905772397da24452332e34b15ea4bae713dd4abc8aa83477dc7
|
7
|
+
data.tar.gz: 953bbc44ca84d32194a231d9037ce8e47917a1895c148e1e0661c7125f24c6bba53e29d9a625b8b6d2744669b49cab99837429c0f22129fad4e6697fafb17988
|
data/.rubocop.yml
CHANGED
@@ -1,7 +1,48 @@
|
|
1
1
|
---
|
2
2
|
|
3
3
|
AllCops:
|
4
|
-
TargetRubyVersion: 2.
|
4
|
+
TargetRubyVersion: 2.4
|
5
5
|
|
6
6
|
Metrics/ClassLength:
|
7
|
-
Max:
|
7
|
+
Max: 150
|
8
|
+
|
9
|
+
# New cops
|
10
|
+
#
|
11
|
+
Lint/RaiseException:
|
12
|
+
Enabled: true
|
13
|
+
Lint/StructNewOverride:
|
14
|
+
Enabled: true
|
15
|
+
Style/ExponentialNotation:
|
16
|
+
Enabled: true
|
17
|
+
Style/HashEachMethods:
|
18
|
+
Enabled: true
|
19
|
+
Style/HashTransformKeys:
|
20
|
+
Enabled: true
|
21
|
+
Style/HashTransformValues:
|
22
|
+
Enabled: true
|
23
|
+
Layout/EmptyLinesAroundAttributeAccessor:
|
24
|
+
Enabled: true
|
25
|
+
Layout/SpaceAroundMethodCallOperator:
|
26
|
+
Enabled: true
|
27
|
+
Style/SlicingWithRange:
|
28
|
+
Enabled: true
|
29
|
+
Lint/DeprecatedOpenSSLConstant:
|
30
|
+
Enabled: true
|
31
|
+
Lint/MixedRegexpCaptureTypes:
|
32
|
+
Enabled: true
|
33
|
+
Style/RedundantRegexpCharacterClass:
|
34
|
+
Enabled: true
|
35
|
+
Style/RedundantRegexpEscape:
|
36
|
+
Enabled: true
|
37
|
+
Style/AccessorGrouping:
|
38
|
+
Enabled: true
|
39
|
+
Style/BisectedAttrAccessor:
|
40
|
+
Enabled: true
|
41
|
+
Style/RedundantAssignment:
|
42
|
+
Enabled: true
|
43
|
+
Style/RedundantFetchBlock:
|
44
|
+
Enabled: true
|
45
|
+
|
46
|
+
# Is nothing sacred?
|
47
|
+
Layout/LineLength:
|
48
|
+
Max: 80
|
data/.travis.yml
CHANGED
data/HISTORY.md
CHANGED
@@ -1,5 +1,37 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 5.1.0 (2020-08-15)
|
4
|
+
* Add `create_aws_external_id`, `delete_aws_external_id`, and
|
5
|
+
`confirm_aws_external_id` methods to `Wavefront::CloudIntegration`.
|
6
|
+
|
7
|
+
## 5.0.1 (2020-07-08)
|
8
|
+
* Reinstate `Wavefront::Role#grant` and `Wavefront::Role#revoke`, which were
|
9
|
+
accidentally removed prior to release of 5.0.0.
|
10
|
+
|
11
|
+
## 5.0.0 (2020-07-08)
|
12
|
+
* Remove `Wavefront::UserGroup#grant` and `Wavefront::UserGroup#revoke` as [the
|
13
|
+
API paths they used have been
|
14
|
+
removed](https://docs.wavefront.com/2020.06.x_release_notes.html#obsolete-and-deprecated-apis).
|
15
|
+
(Breaking change.)
|
16
|
+
* Remove `Wavefront::MonitoredCluster` class, as it has been removed from the
|
17
|
+
public API.
|
18
|
+
* Deprecate `Wavefront::User` class, as [the user API is now
|
19
|
+
deprecated](https://docs.wavefront.com/2020.06.x_release_notes.html#obsolete-and-deprecated-apis)
|
20
|
+
* Add `Wavefront::Role` class, for managing roles.
|
21
|
+
* Promote `Wavefront::Spy` class from unstable. It is now an official API.
|
22
|
+
|
23
|
+
## 4.0.0 (2020-02-17)
|
24
|
+
* Drop support for Ruby 2.3. (Breaking change.)
|
25
|
+
* Add `Wavefront::MonitoredCluster` class.
|
26
|
+
* Add `Wavefront::Unstable::Spy` class to speak to (undocumented) spy
|
27
|
+
interface.
|
28
|
+
* Add `Wavefront::Unstable::Chart` class to speak to (undocumented) chart
|
29
|
+
interface.
|
30
|
+
|
31
|
+
## 3.7.1 (2020-02-09)
|
32
|
+
* `Response` object returned by `Wavefront::Write#write` includes a valid HTTP
|
33
|
+
code, rather than `nil`.
|
34
|
+
|
3
35
|
## 3.7.0 (2020-01-23)
|
4
36
|
* Add `Account`, `Usage` and `IngestionPolicy` classes.
|
5
37
|
* Allow modification of `Wavefront::Response`'s `response` object.
|
data/README.md
CHANGED
@@ -24,7 +24,7 @@ or to build locally,
|
|
24
24
|
$ gem build wavefront-sdk.gemspec
|
25
25
|
```
|
26
26
|
|
27
|
-
`wavefront-sdk` requires Ruby >= 2.
|
27
|
+
`wavefront-sdk` requires Ruby >= 2.4. All its dependencies are pure
|
28
28
|
Ruby, right the way down, so a compiler should never be required to
|
29
29
|
install it.
|
30
30
|
|
@@ -100,10 +100,11 @@ when you ask for a list of objects.
|
|
100
100
|
|
101
101
|
You can set an offset and a limit when you list, but setting the
|
102
102
|
limit to the magic value `:all` will return all items, without you
|
103
|
-
having to deal with pagination.
|
103
|
+
having to deal with pagination. When you do that, `offset` is repurposed as
|
104
|
+
the number of results fetched with each call to the API.
|
104
105
|
|
105
106
|
Calling a method with the limit set to `:lazy` returns a lazy
|
106
|
-
enumerable.
|
107
|
+
enumerable. Again, `offset` is the chunk size.
|
107
108
|
|
108
109
|
```ruby
|
109
110
|
wf = Wavefront::Alert.new(creds.all)
|
@@ -44,6 +44,18 @@ module Wavefront
|
|
44
44
|
api.get(id)
|
45
45
|
end
|
46
46
|
|
47
|
+
# POST /api/v2/account/{id}/addRoles
|
48
|
+
# Add specific roles to the account (user or service account)
|
49
|
+
# @param id [String] ID of the account
|
50
|
+
# @param role_list [Array[String]] list of roles to add
|
51
|
+
# @return [Wavefront::Response]
|
52
|
+
#
|
53
|
+
def add_roles(id, role_list)
|
54
|
+
wf_account_id?(id)
|
55
|
+
validate_role_list(role_list)
|
56
|
+
api.post([id, 'addRoles'].uri_concat, role_list, 'application/json')
|
57
|
+
end
|
58
|
+
|
47
59
|
# POST /api/v2/account/{id}/addUserGroups
|
48
60
|
# Adds specific user groups to the account (user or service account)
|
49
61
|
# @param id [String] ID of the account
|
@@ -68,10 +80,22 @@ module Wavefront
|
|
68
80
|
api.get([id, 'businessFunctions'].uri_concat)
|
69
81
|
end
|
70
82
|
|
83
|
+
# POST /api/v2/account/{id}/removeRoles
|
84
|
+
# Removes specific roles from the account (user or service account)
|
85
|
+
# @param id [String] ID of the account
|
86
|
+
# @param role_list [Array[String]] list of roles to remove
|
87
|
+
# @return [Wavefront::Response]
|
88
|
+
#
|
89
|
+
def remove_roles(id, role_list)
|
90
|
+
wf_account_id?(id)
|
91
|
+
validate_role_list(role_list)
|
92
|
+
api.post([id, 'removeRoles'].uri_concat, role_list, 'application/json')
|
93
|
+
end
|
94
|
+
|
71
95
|
# POST /api/v2/account/{id}/removeUserGroups
|
72
96
|
# Removes specific user groups from the account (user or service account)
|
73
97
|
# @param id [String] ID of the account
|
74
|
-
# @param group_list [Array[String]] list of groups to
|
98
|
+
# @param group_list [Array[String]] list of groups to remove
|
75
99
|
# @return [Wavefront::Response]
|
76
100
|
#
|
77
101
|
def remove_user_groups(id, group_list)
|
@@ -132,7 +156,8 @@ module Wavefront
|
|
132
156
|
end
|
133
157
|
|
134
158
|
# POST /api/v2/account/removeingestionpolicies
|
135
|
-
# Removes ingestion policies from multiple accounts
|
159
|
+
# Removes ingestion policies from multiple accounts. The API path says
|
160
|
+
# "policies" but I've made the method name "policy" for consistency.
|
136
161
|
# @param policy_id [String] ID of the ingestion policy
|
137
162
|
# @param id_list [Array[String]] list of accounts to be put in policy
|
138
163
|
# @return [Wavefront::Response]
|
@@ -140,7 +165,7 @@ module Wavefront
|
|
140
165
|
def remove_ingestion_policy(policy_id, id_list)
|
141
166
|
wf_ingestionpolicy_id?(policy_id)
|
142
167
|
validate_account_list(id_list)
|
143
|
-
api.post('
|
168
|
+
api.post('removeingestionpolicies',
|
144
169
|
{ ingestionPolicyId: policy_id,
|
145
170
|
accounts: id_list },
|
146
171
|
'application/json')
|
@@ -157,6 +182,78 @@ module Wavefront
|
|
157
182
|
api.post('deleteAccounts', id_list, 'application/json')
|
158
183
|
end
|
159
184
|
|
185
|
+
# GET /api/v2/account/user
|
186
|
+
# Get all user accounts
|
187
|
+
# @param offset [Int] user account at which the list begins
|
188
|
+
# @param limit [Int] the number of user accounts to return
|
189
|
+
# @return [Wavefront::Response]
|
190
|
+
#
|
191
|
+
def user_list(offset = 0, limit = 100)
|
192
|
+
api.get('user', offset: offset, limit: limit)
|
193
|
+
end
|
194
|
+
|
195
|
+
def user_create(body, send_email = false)
|
196
|
+
raise ArgumentError unless body.is_a?(Hash)
|
197
|
+
|
198
|
+
uri = send_email ? "?sendEmail=#{send_email}" : 'user'
|
199
|
+
|
200
|
+
api.post(uri, body, 'application/json')
|
201
|
+
end
|
202
|
+
|
203
|
+
# POST /api/v2/account/user
|
204
|
+
# Creates or updates a user account
|
205
|
+
# @param id [String] a Wavefront user ID
|
206
|
+
# @param body [Hash] key-value hash of the parameters you wish to change
|
207
|
+
# @param modify [true, false] if true, use {#describe()} to get a hash
|
208
|
+
# describing the existing object, and modify that with the new body. If
|
209
|
+
# false, pass the new body straight through.
|
210
|
+
# @return [Wavefront::Response]
|
211
|
+
def user_update(body, modify = true)
|
212
|
+
raise ArgumentError unless body.is_a?(Hash)
|
213
|
+
|
214
|
+
return api.post('user', body, 'application/json') unless modify
|
215
|
+
|
216
|
+
api.post('user',
|
217
|
+
hash_for_update(describe(id).response, body),
|
218
|
+
'application/json')
|
219
|
+
end
|
220
|
+
|
221
|
+
# GET /api/v2/account/user/{id}
|
222
|
+
# Retrieves a user by identifier (email address)
|
223
|
+
# @param id [String] ID of the proxy
|
224
|
+
# @return [Wavefront::Response]
|
225
|
+
#
|
226
|
+
def user_describe(id)
|
227
|
+
wf_user_id?(id)
|
228
|
+
api.get(['user', id].uri_concat)
|
229
|
+
end
|
230
|
+
|
231
|
+
# POST /api/v2/account/user/invite
|
232
|
+
# Invite user accounts with given user groups and permissions.
|
233
|
+
# @param body [Array[Hash]] array of hashes, each hash describing a user.
|
234
|
+
# See API docs for more details. It is your responsibility to validate
|
235
|
+
# the data which describes each user.
|
236
|
+
# @return [Wavefront::Response]
|
237
|
+
#
|
238
|
+
def user_invite(body)
|
239
|
+
raise ArgumentError unless body.is_a?(Array)
|
240
|
+
raise ArgumentError unless body.first.is_a?(Hash)
|
241
|
+
|
242
|
+
api.post('user/invite', body, 'application/json')
|
243
|
+
end
|
244
|
+
|
245
|
+
# POST /api/v2/account/validateAccounts
|
246
|
+
# Returns valid accounts (users and service accounts), also invalid
|
247
|
+
# identifiers from the given list
|
248
|
+
# @param id_list [Array[String]] list of user IDs
|
249
|
+
# @return [Wavefront::Response]
|
250
|
+
#
|
251
|
+
def validate_accounts(id_list)
|
252
|
+
raise ArgumentError unless id_list.is_a?(Array)
|
253
|
+
|
254
|
+
api.post('validateAccounts', id_list, 'application/json')
|
255
|
+
end
|
256
|
+
|
160
257
|
private
|
161
258
|
|
162
259
|
# @param id [String] ID of the user
|
@@ -198,5 +295,9 @@ module Wavefront
|
|
198
295
|
wf_permission?(permission)
|
199
296
|
api.post(['revoke', permission].uri_concat, id_list, 'application/json')
|
200
297
|
end
|
298
|
+
|
299
|
+
def update_keys
|
300
|
+
%i[identifier groups userGroups roles ingestionPolicyId]
|
301
|
+
end
|
201
302
|
end
|
202
303
|
end
|
@@ -35,6 +35,16 @@ module Wavefront
|
|
35
35
|
|
36
36
|
list.each { |id| wf_account_id?(id) }
|
37
37
|
end
|
38
|
+
|
39
|
+
# Validate a list of roles
|
40
|
+
# @param list [Array[String]] list of role IDs
|
41
|
+
# @raise Wavefront::Exception::InvalidRole
|
42
|
+
#
|
43
|
+
def validate_role_list(list)
|
44
|
+
raise ArgumentError unless list.is_a?(Array)
|
45
|
+
|
46
|
+
list.each { |id| wf_role_id?(id) }
|
47
|
+
end
|
38
48
|
end
|
39
49
|
end
|
40
50
|
end
|
@@ -101,5 +101,32 @@ module Wavefront
|
|
101
101
|
wf_cloudintegration_id?(id)
|
102
102
|
api.post([id, 'undelete'].uri_concat)
|
103
103
|
end
|
104
|
+
|
105
|
+
# POST /api/v2/cloudintegration/awsExternalIdCreate an external id
|
106
|
+
# @return [Wavefront::Response]
|
107
|
+
#
|
108
|
+
def create_aws_external_id
|
109
|
+
api.post('awsExternalId', nil, 'application/json')
|
110
|
+
end
|
111
|
+
|
112
|
+
# DELETE /api/v2/cloudintegration/awsExternalId/{id}DELETEs an external id
|
113
|
+
# that was created by Wavefront
|
114
|
+
# @param id [String] AWS external ID
|
115
|
+
# @return [Wavefront::Response]
|
116
|
+
#
|
117
|
+
def delete_aws_external_id(external_id)
|
118
|
+
wf_aws_external_id?(external_id)
|
119
|
+
api.delete(['awsExternalId', external_id].uri_concat)
|
120
|
+
end
|
121
|
+
|
122
|
+
# GET /api/v2/cloudintegration/awsExternalId/{id}GETs (confirms) a valid
|
123
|
+
# external id that was created by Wavefront
|
124
|
+
# @param id [String] AWS external ID
|
125
|
+
# @return [Wavefront::Response]
|
126
|
+
#
|
127
|
+
def confirm_aws_external_id(external_id)
|
128
|
+
wf_aws_external_id?(external_id)
|
129
|
+
api.get(['awsExternalId', external_id].uri_concat)
|
130
|
+
end
|
104
131
|
end
|
105
132
|
end
|
@@ -6,6 +6,7 @@ require 'addressable'
|
|
6
6
|
require_relative 'response'
|
7
7
|
require_relative '../defs/version'
|
8
8
|
require_relative '../support/mixins'
|
9
|
+
require_relative '../stdlib/time'
|
9
10
|
|
10
11
|
module Wavefront
|
11
12
|
#
|
@@ -78,14 +79,47 @@ module Wavefront
|
|
78
79
|
# was cleaner to add this method. Parameters are same as #get.
|
79
80
|
#
|
80
81
|
def get_flat_params(path, query = {})
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
82
|
+
make_call(flat_param_conn(path, query), :get)
|
83
|
+
end
|
84
|
+
|
85
|
+
# This is used by the Wavefront::Unstable::Spy methods to stream data.
|
86
|
+
# It prints to standard out.
|
87
|
+
# @param path [String] path to be appended to the net[:api_base] path.
|
88
|
+
# @param query [Hash] optional key-value pairs with will be made into a
|
89
|
+
# query string
|
90
|
+
# @param opts [Hash] keys:
|
91
|
+
# timestamp_chunks -- prints a timestamp before each chunk of streamed
|
92
|
+
# data
|
93
|
+
# timeout -- after approximately this many seconds, return. It will be
|
94
|
+
# the first chunk *after* the given time
|
95
|
+
# @return
|
96
|
+
#
|
97
|
+
def get_stream(path, query = {}, opts = {})
|
98
|
+
conn = flat_param_conn(path, query)
|
99
|
+
verbosity(conn, :get, query)
|
100
|
+
stream_connection(conn, query, opts)
|
101
|
+
rescue Faraday::TimeoutError
|
102
|
+
raise Wavefront::Exception::NetworkTimeout
|
103
|
+
rescue StopIteration
|
104
|
+
nil
|
105
|
+
end
|
106
|
+
|
107
|
+
def stream_connection(conn, query, opts)
|
108
|
+
t_end = end_time(opts)
|
109
|
+
|
110
|
+
conn.get do |req|
|
111
|
+
req.params = query
|
112
|
+
req.options.on_data = proc do |chunk, _size|
|
113
|
+
raise StopIteration if t_end && Time.right_now >= t_end
|
87
114
|
|
88
|
-
|
115
|
+
puts Time.now if opts[:timestamp_chunks]
|
116
|
+
puts chunk
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def end_time(opts)
|
122
|
+
Time.right_now + opts[:timeout] if opts[:timeout]&.positive?
|
89
123
|
end
|
90
124
|
|
91
125
|
# Make a POST call to the Wavefront API and return the result as
|
@@ -240,5 +274,14 @@ module Wavefront
|
|
240
274
|
end
|
241
275
|
end
|
242
276
|
end
|
277
|
+
|
278
|
+
def flat_param_conn(path, query)
|
279
|
+
mk_conn(path,
|
280
|
+
{},
|
281
|
+
request: {
|
282
|
+
params_encoder: Faraday::FlatParamsEncoder
|
283
|
+
},
|
284
|
+
params: query)
|
285
|
+
end
|
243
286
|
end
|
244
287
|
end
|
@@ -12,6 +12,7 @@ module Wavefront
|
|
12
12
|
class InvalidAlertId < RuntimeError; end
|
13
13
|
class InvalidAlertSeverity < RuntimeError; end
|
14
14
|
class InvalidApiTokenId < RuntimeError; end
|
15
|
+
class InvalidAwsExternalId < RuntimeError; end
|
15
16
|
class InvalidConfigFile < RuntimeError; end
|
16
17
|
class InvalidCloudIntegrationId < RuntimeError; end
|
17
18
|
class InvalidDashboardId < RuntimeError; end
|
@@ -28,6 +29,7 @@ module Wavefront
|
|
28
29
|
class InvalidIntegrationId < RuntimeError; end
|
29
30
|
class InvalidLinkTemplate < RuntimeError; end
|
30
31
|
class InvalidMaintenanceWindowId < RuntimeError; end
|
32
|
+
class InvalidMonitoredClusterId < RuntimeError; end
|
31
33
|
class InvalidMessageId < RuntimeError; end
|
32
34
|
class InvalidMetricName < RuntimeError; end
|
33
35
|
class InvalidMetricValue < RuntimeError; end
|
@@ -37,7 +39,9 @@ module Wavefront
|
|
37
39
|
class InvalidPoint < RuntimeError; end
|
38
40
|
class InvalidPrefixLength < RuntimeError; end
|
39
41
|
class InvalidProxyId < RuntimeError; end
|
42
|
+
class InvalidRoleId < RuntimeError; end
|
40
43
|
class InvalidRelativeTime < RuntimeError; end
|
44
|
+
class InvalidSamplingValue < RuntimeError; end
|
41
45
|
class InvalidSavedSearchEntity < RuntimeError; end
|
42
46
|
class InvalidSavedSearchId < RuntimeError; end
|
43
47
|
class InvalidServiceAccountId < RuntimeError; end
|
@@ -51,6 +55,7 @@ module Wavefront
|
|
51
55
|
class InvalidUserGroupId < RuntimeError; end
|
52
56
|
class InvalidVersion < RuntimeError; end
|
53
57
|
class InvalidWebhookId < RuntimeError; end
|
58
|
+
class NetworkTimeout < RuntimeError; end
|
54
59
|
class NotImplemented < RuntimeError; end
|
55
60
|
class SocketError < RuntimeError; end
|
56
61
|
class UnparseableResponse < RuntimeError; end
|