wavefront-sdk 3.7.0 → 5.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|