hcloud 0.1.2 → 1.0.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 +5 -5
- data/.gitignore +0 -1
- data/.rubocop.yml +24 -9
- data/.rubocop_todo.yml +18 -121
- data/.travis.yml +3 -3
- data/CHANGELOG.md +13 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +143 -0
- data/README.md +34 -1
- data/Rakefile +2 -0
- data/bin/console +1 -0
- data/hcloud.gemspec +5 -3
- data/lib/hcloud.rb +31 -5
- data/lib/hcloud/abstract_resource.rb +162 -55
- data/lib/hcloud/action.rb +8 -10
- data/lib/hcloud/action_resource.rb +3 -29
- data/lib/hcloud/client.rb +66 -28
- data/lib/hcloud/datacenter.rb +7 -7
- data/lib/hcloud/datacenter_resource.rb +6 -31
- data/lib/hcloud/entry_loader.rb +181 -20
- data/lib/hcloud/errors.rb +2 -0
- data/lib/hcloud/floating_ip.rb +18 -29
- data/lib/hcloud/floating_ip_resource.rb +15 -30
- data/lib/hcloud/image.rb +12 -32
- data/lib/hcloud/image_resource.rb +7 -38
- data/lib/hcloud/iso.rb +4 -1
- data/lib/hcloud/iso_resource.rb +7 -28
- data/lib/hcloud/location.rb +3 -9
- data/lib/hcloud/location_resource.rb +6 -27
- data/lib/hcloud/network.rb +33 -0
- data/lib/hcloud/network_resource.rb +25 -0
- data/lib/hcloud/pagination.rb +2 -9
- data/lib/hcloud/server.rb +37 -70
- data/lib/hcloud/server_resource.rb +16 -36
- data/lib/hcloud/server_type.rb +3 -10
- data/lib/hcloud/server_type_resource.rb +6 -28
- data/lib/hcloud/ssh_key.rb +6 -17
- data/lib/hcloud/ssh_key_resource.rb +13 -32
- data/lib/hcloud/typhoeus_ext.rb +112 -0
- data/lib/hcloud/version.rb +3 -1
- data/lib/hcloud/volume.rb +32 -0
- data/lib/hcloud/volume_resource.rb +29 -0
- metadata +31 -13
- data/lib/hcloud/multi_reply.rb +0 -21
data/Rakefile
CHANGED
data/bin/console
CHANGED
data/hcloud.gemspec
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
|
-
lib = File.expand_path('
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'hcloud/version'
|
5
6
|
|
@@ -19,10 +20,11 @@ Gem::Specification.new do |spec|
|
|
19
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
21
|
spec.require_paths = ['lib']
|
21
22
|
|
23
|
+
spec.add_development_dependency 'activemodel'
|
22
24
|
spec.add_development_dependency 'activesupport'
|
23
|
-
spec.add_development_dependency 'bundler'
|
25
|
+
spec.add_development_dependency 'bundler'
|
24
26
|
spec.add_development_dependency 'grape'
|
25
|
-
spec.add_development_dependency 'rake'
|
27
|
+
spec.add_development_dependency 'rake'
|
26
28
|
spec.add_development_dependency 'rspec'
|
27
29
|
spec.add_development_dependency 'webmock'
|
28
30
|
spec.add_runtime_dependency 'activesupport'
|
data/lib/hcloud.rb
CHANGED
@@ -1,29 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'hcloud/version'
|
2
4
|
require 'active_support/core_ext/object/to_query'
|
5
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
3
6
|
|
4
7
|
module Hcloud
|
5
8
|
autoload :Error, 'hcloud/errors'
|
6
9
|
autoload :Client, 'hcloud/client'
|
10
|
+
autoload :TyphoeusExt, 'hcloud/typhoeus_ext'
|
7
11
|
autoload :AbstractResource, 'hcloud/abstract_resource'
|
8
|
-
autoload :MultiReply, 'hcloud/multi_reply'
|
9
|
-
autoload :ServerResource, 'hcloud/server_resource'
|
10
12
|
autoload :EntryLoader, 'hcloud/entry_loader'
|
13
|
+
|
14
|
+
autoload :Server, 'hcloud/server'
|
15
|
+
autoload :ServerResource, 'hcloud/server_resource'
|
16
|
+
|
17
|
+
autoload :ServerType, 'hcloud/server_type'
|
18
|
+
autoload :ServerTypeResource, 'hcloud/server_type_resource'
|
19
|
+
|
11
20
|
autoload :FloatingIP, 'hcloud/floating_ip'
|
12
21
|
autoload :FloatingIPResource, 'hcloud/floating_ip_resource'
|
22
|
+
|
13
23
|
autoload :SSHKey, 'hcloud/ssh_key'
|
14
24
|
autoload :SSHKeyResource, 'hcloud/ssh_key_resource'
|
15
|
-
|
16
|
-
autoload :ServerType, 'hcloud/server_type'
|
17
|
-
autoload :ServerTypeResource, 'hcloud/server_type_resource'
|
25
|
+
|
18
26
|
autoload :Datacenter, 'hcloud/datacenter'
|
19
27
|
autoload :DatacenterResource, 'hcloud/datacenter_resource'
|
28
|
+
|
20
29
|
autoload :Location, 'hcloud/location'
|
21
30
|
autoload :LocationResource, 'hcloud/location_resource'
|
31
|
+
|
22
32
|
autoload :Image, 'hcloud/image'
|
23
33
|
autoload :ImageResource, 'hcloud/image_resource'
|
34
|
+
|
35
|
+
autoload :Network, 'hcloud/network'
|
36
|
+
autoload :NetworkResource, 'hcloud/network_resource'
|
37
|
+
|
38
|
+
autoload :Volume, 'hcloud/volume'
|
39
|
+
autoload :VolumeResource, 'hcloud/volume_resource'
|
40
|
+
|
24
41
|
autoload :Action, 'hcloud/action'
|
25
42
|
autoload :ActionResource, 'hcloud/action_resource'
|
43
|
+
|
26
44
|
autoload :Iso, 'hcloud/iso'
|
27
45
|
autoload :IsoResource, 'hcloud/iso_resource'
|
46
|
+
|
28
47
|
autoload :Pagination, 'hcloud/pagination'
|
48
|
+
|
49
|
+
COLLECT_ARGS = proc do |method_name, bind|
|
50
|
+
query = bind.receiver.method(method_name).parameters.inject({}) do |hash, (_type, name)|
|
51
|
+
hash.merge(name => bind.local_variable_get(name))
|
52
|
+
end
|
53
|
+
query.delete_if { |_, v| v.nil? }
|
54
|
+
end
|
29
55
|
end
|
@@ -1,75 +1,185 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/string'
|
4
|
+
|
1
5
|
module Hcloud
|
2
6
|
class AbstractResource
|
3
7
|
include Enumerable
|
4
8
|
|
5
|
-
|
9
|
+
delegate :request, :prepare_request, to: :client
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def bind_to(klass)
|
13
|
+
resource = self
|
14
|
+
%w[find find_by where all [] page limit per_page order
|
15
|
+
to_a count pagnation each].each do |method|
|
16
|
+
klass.define_singleton_method(method) do |*args, &block|
|
17
|
+
resource.new(client: Client.connection).public_send(method, *args, &block)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def filter_attributes(*keys)
|
23
|
+
return @filter_attributes if keys.to_a.empty?
|
24
|
+
|
25
|
+
@filter_attributes = keys
|
26
|
+
end
|
27
|
+
|
28
|
+
def resource_class
|
29
|
+
ancestors[ancestors.index(Hcloud::AbstractResource) - 1]
|
30
|
+
end
|
31
|
+
|
32
|
+
def resource_url(url = nil)
|
33
|
+
return (@resource_url = url) if url
|
34
|
+
|
35
|
+
@resource_url || resource_class.name.demodulize.gsub('Resource', '').tableize
|
36
|
+
end
|
37
|
+
|
38
|
+
def resource_path(path = nil)
|
39
|
+
return (@resource_path = path) if path
|
40
|
+
|
41
|
+
@resource_path || resource_url
|
42
|
+
end
|
6
43
|
|
7
|
-
|
44
|
+
def resource(res = nil)
|
45
|
+
return (@resource = res) if res
|
46
|
+
return @resource if @resource
|
47
|
+
|
48
|
+
auto_const = resource_class.name.demodulize.gsub('Resource', '').to_sym
|
49
|
+
return Hcloud.const_get(auto_const) if Hcloud.constants.include?(auto_const)
|
50
|
+
|
51
|
+
raise Error, "unable to lookup resource class for #{name}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
attr_reader :client
|
56
|
+
|
57
|
+
def initialize(client:, base_path: '')
|
8
58
|
@client = client
|
9
|
-
@parent = parent
|
10
59
|
@page = 1
|
11
60
|
@per_page = 25
|
12
61
|
@order = []
|
13
62
|
@base_path = base_path
|
14
63
|
end
|
15
64
|
|
65
|
+
def all
|
66
|
+
where
|
67
|
+
end
|
68
|
+
|
69
|
+
def where(**kwargs)
|
70
|
+
kwargs.keys.each do |key|
|
71
|
+
keys = self.class.filter_attributes.map(&:to_s)
|
72
|
+
next if keys.include?(key.to_s)
|
73
|
+
|
74
|
+
raise ArgumentError, "unknown filter #{key}, allowed keys are #{keys}"
|
75
|
+
end
|
76
|
+
|
77
|
+
_dup :@query, @query.to_h.merge(kwargs)
|
78
|
+
end
|
79
|
+
|
80
|
+
def find(id)
|
81
|
+
prepare_request(
|
82
|
+
[self.class.resource_url, id].join('/'),
|
83
|
+
resource_path: resource_path.to_s.singularize,
|
84
|
+
resource_class: self.class.resource
|
85
|
+
)
|
86
|
+
end
|
87
|
+
|
88
|
+
def [](arg)
|
89
|
+
find_by(id: arg)
|
90
|
+
end
|
91
|
+
|
92
|
+
def find_by(**kwargs)
|
93
|
+
if id = kwargs.delete(:id)
|
94
|
+
return find(id)
|
95
|
+
end
|
96
|
+
|
97
|
+
per_page(1).where(**kwargs).first
|
98
|
+
rescue Error::NotFound
|
99
|
+
end
|
100
|
+
|
101
|
+
# def count
|
102
|
+
# per_page(1).first&.response&.pagination&.total_entries.to_i
|
103
|
+
# end
|
104
|
+
|
16
105
|
def page(page)
|
17
|
-
|
18
|
-
self
|
106
|
+
_dup :@page, page
|
19
107
|
end
|
20
108
|
|
21
109
|
def per_page(per_page)
|
22
|
-
|
23
|
-
self
|
110
|
+
_dup :@per_page, per_page
|
24
111
|
end
|
25
112
|
|
26
113
|
def limit(limit)
|
27
|
-
|
28
|
-
self
|
114
|
+
_dup :@limit, limit
|
29
115
|
end
|
30
116
|
|
31
117
|
def order(*sort)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
118
|
+
_dup :@order,
|
119
|
+
begin
|
120
|
+
sort.flat_map do |s|
|
121
|
+
case s
|
122
|
+
when Symbol, String then s.to_s
|
123
|
+
when Hash then s.map { |k, v| "#{k}:#{v}" }
|
124
|
+
else
|
125
|
+
raise ArgumentError,
|
126
|
+
"Unable to resolve type for given #{s.inspect} from #{sort}"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
42
130
|
end
|
43
131
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
52
|
-
client.hydra.run
|
53
|
-
j = requests.map do |x|
|
54
|
-
Oj.load(x.response.body)
|
55
|
-
end
|
56
|
-
m = MultiReply.new(j: j, pagination: :auto)
|
57
|
-
m.cb = block
|
58
|
-
return m
|
59
|
-
end
|
60
|
-
m = MultiReply.new(j: [Oj.load(request(path, o.merge(ep: ep)).run.body)])
|
61
|
-
m.cb = block
|
62
|
-
m
|
132
|
+
def run
|
133
|
+
@run ||= multi_query(
|
134
|
+
resource_url,
|
135
|
+
q: @query,
|
136
|
+
resource_path: resource_path,
|
137
|
+
resource_class: self.class.resource
|
138
|
+
)
|
63
139
|
end
|
64
140
|
|
65
141
|
def each
|
66
|
-
|
142
|
+
run.each do |member|
|
67
143
|
yield(member)
|
68
144
|
end
|
69
145
|
end
|
70
146
|
|
147
|
+
# this is just to keep the actual bevahior
|
148
|
+
def pagination
|
149
|
+
return :auto if client.auto_pagination
|
150
|
+
|
151
|
+
run.response.pagination
|
152
|
+
end
|
153
|
+
|
71
154
|
protected
|
72
155
|
|
156
|
+
def _dup(var, value)
|
157
|
+
dup.tap do |res|
|
158
|
+
res.instance_variable_set(var, value)
|
159
|
+
res.instance_variable_set(:@run, nil)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def resource_path
|
164
|
+
self.class.resource_path || self.class.resource_url
|
165
|
+
end
|
166
|
+
|
167
|
+
def resource_url
|
168
|
+
[@base_path.to_s, self.class.resource_url.to_s].reject(&:empty?).join('/')
|
169
|
+
end
|
170
|
+
|
171
|
+
def multi_query(path, **o)
|
172
|
+
return prepare_request(path, o.merge(ep: ep)) unless client&.auto_pagination
|
173
|
+
|
174
|
+
raise Error, 'unable to run auto paginate within concurrent excecution' if @concurrent
|
175
|
+
|
176
|
+
requests = __entries__(path, **o)
|
177
|
+
return requests.flat_map(&:resource) if requests.all? { |req| req.respond_to? :resource }
|
178
|
+
|
179
|
+
client.hydra.run
|
180
|
+
requests.flat_map { |req| req.response.resource }
|
181
|
+
end
|
182
|
+
|
73
183
|
def page_params(per_page: nil, page: nil)
|
74
184
|
{ per_page: per_page || @per_page, page: page || @page }.to_param
|
75
185
|
end
|
@@ -85,27 +195,24 @@ module Hcloud
|
|
85
195
|
r.compact.join('&')
|
86
196
|
end
|
87
197
|
|
88
|
-
def request(*args)
|
89
|
-
client.request(*args)
|
90
|
-
end
|
91
|
-
|
92
198
|
def __entries__(path, **o)
|
93
|
-
|
94
|
-
|
95
|
-
return [
|
199
|
+
first_page = request(path, o.merge(ep: ep(per_page: 1, page: 1))).run
|
200
|
+
total_entries = first_page.pagination.total_entries
|
201
|
+
return [first_page] if total_entries <= 1 || @limit == 1
|
202
|
+
|
96
203
|
unless @limit.nil?
|
97
|
-
|
204
|
+
total_entries = @limit if total_entries > @limit
|
98
205
|
end
|
99
|
-
|
100
|
-
|
101
|
-
|
206
|
+
pages = total_entries / Client::MAX_ENTRIES_PER_PAGE
|
207
|
+
pages += 1 if (total_entries % Client::MAX_ENTRIES_PER_PAGE).positive?
|
208
|
+
pages.times.map do |page|
|
102
209
|
per_page = Client::MAX_ENTRIES_PER_PAGE
|
103
|
-
if !@limit.nil? && (
|
104
|
-
per_page =
|
210
|
+
if !@limit.nil? && (pages == (page + 1)) && (total_entries % per_page != 0)
|
211
|
+
per_page = total_entries % per_page
|
212
|
+
end
|
213
|
+
request(path, o.merge(ep: ep(per_page: per_page, page: page + 1))).tap do |req|
|
214
|
+
client.hydra.queue req
|
105
215
|
end
|
106
|
-
req = request(path, o.merge(ep: ep(per_page: per_page, page: i + 1)))
|
107
|
-
client.hydra.queue req
|
108
|
-
req
|
109
216
|
end
|
110
217
|
end
|
111
218
|
end
|
data/lib/hcloud/action.rb
CHANGED
@@ -1,16 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Hcloud
|
2
4
|
class Action
|
3
|
-
|
4
|
-
id: nil,
|
5
|
-
command: nil,
|
6
|
-
status: nil,
|
7
|
-
progress: nil,
|
8
|
-
started: :time,
|
9
|
-
finished: :time,
|
10
|
-
resources: nil,
|
11
|
-
error: nil
|
12
|
-
}.freeze
|
5
|
+
require 'hcloud/action_resource'
|
13
6
|
|
14
7
|
include EntryLoader
|
8
|
+
|
9
|
+
schema(
|
10
|
+
started: :time,
|
11
|
+
finished: :time
|
12
|
+
)
|
15
13
|
end
|
16
14
|
end
|
@@ -1,35 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
module Hcloud
|
3
4
|
class ActionResource < AbstractResource
|
4
|
-
|
5
|
-
mj(base_path('actions')) do |j|
|
6
|
-
j.flat_map { |x| x['actions'].map { |x| Action.new(x, self, client) } }
|
7
|
-
end
|
8
|
-
end
|
5
|
+
filter_attributes :status
|
9
6
|
|
10
|
-
|
11
|
-
Action.new(
|
12
|
-
Oj.load(request(base_path("actions/#{id.to_i}")).run.body)['action'],
|
13
|
-
self,
|
14
|
-
client
|
15
|
-
)
|
16
|
-
end
|
17
|
-
|
18
|
-
def [](arg)
|
19
|
-
find(arg)
|
20
|
-
rescue Error::NotFound
|
21
|
-
end
|
22
|
-
|
23
|
-
def where(status: nil)
|
24
|
-
mj(base_path('actions'), q: { status: status }) do |j|
|
25
|
-
j.flat_map { |x| x['actions'].map { |x| Action.new(x, self, client) } }
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def base_path(ext)
|
32
|
-
[@base_path, ext].reject(&:empty?).join('/')
|
33
|
-
end
|
7
|
+
bind_to Action
|
34
8
|
end
|
35
9
|
end
|
data/lib/hcloud/client.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
autoload :Typhoeus, 'typhoeus'
|
2
4
|
autoload :Oj, 'oj'
|
3
5
|
|
@@ -5,14 +7,43 @@ module Hcloud
|
|
5
7
|
class Client
|
6
8
|
MAX_ENTRIES_PER_PAGE = 50
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
+
class << self
|
11
|
+
attr_writer :connection
|
12
|
+
|
13
|
+
def connection
|
14
|
+
return @connection if @connection.is_a? Hcloud::Client
|
15
|
+
|
16
|
+
raise ArgumentError, "client not correctly initialized, actually #{@client.inspect}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :token, :auto_pagination, :hydra, :user_agent
|
21
|
+
def initialize(token:, auto_pagination: false, concurrency: 20, user_agent: nil)
|
10
22
|
@token = token
|
23
|
+
@user_agent = user_agent || "hcloud-ruby v#{VERSION}"
|
11
24
|
@auto_pagination = auto_pagination
|
12
25
|
@concurrency = concurrency
|
13
26
|
@hydra = Typhoeus::Hydra.new(max_concurrency: concurrency)
|
14
27
|
end
|
15
28
|
|
29
|
+
def concurrent
|
30
|
+
@concurrent = true
|
31
|
+
ret = yield
|
32
|
+
ret.each do |element|
|
33
|
+
next unless element.is_a?(AbstractResource)
|
34
|
+
|
35
|
+
element.run
|
36
|
+
end
|
37
|
+
hydra.run
|
38
|
+
ret
|
39
|
+
ensure
|
40
|
+
@concurrent = nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def concurrent?
|
44
|
+
!@concurrent.nil?
|
45
|
+
end
|
46
|
+
|
16
47
|
def authorized?
|
17
48
|
request('server_types').run
|
18
49
|
true
|
@@ -56,8 +87,34 @@ module Hcloud
|
|
56
87
|
FloatingIPResource.new(client: self)
|
57
88
|
end
|
58
89
|
|
59
|
-
def
|
60
|
-
|
90
|
+
def networks
|
91
|
+
NetworkResource.new(client: self)
|
92
|
+
end
|
93
|
+
|
94
|
+
def volumes
|
95
|
+
VolumeResource.new(client: self)
|
96
|
+
end
|
97
|
+
|
98
|
+
class ResourceFuture < Delegator
|
99
|
+
def initialize(request)
|
100
|
+
@request = request
|
101
|
+
end
|
102
|
+
|
103
|
+
def __getobj__
|
104
|
+
@__getobj__ ||= @request&.response&.resource
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def prepare_request(url, **args, &block)
|
109
|
+
req = request(url, **args.merge(block: block))
|
110
|
+
return req.run.resource unless concurrent?
|
111
|
+
|
112
|
+
hydra.queue req
|
113
|
+
ResourceFuture.new(req)
|
114
|
+
end
|
115
|
+
|
116
|
+
def request(path, **options) # rubocop:disable Metrics/MethodLength
|
117
|
+
hcloud_attributes = TyphoeusExt.collect_attributes(options)
|
61
118
|
if x = options.delete(:j)
|
62
119
|
options[:body] = Oj.dump(x, mode: :compat)
|
63
120
|
options[:method] ||= :post
|
@@ -74,35 +131,16 @@ module Hcloud
|
|
74
131
|
{
|
75
132
|
headers: {
|
76
133
|
'Authorization' => "Bearer #{token}",
|
134
|
+
'User-Agent' => user_agent,
|
77
135
|
'Content-Type' => 'application/json'
|
78
136
|
}
|
79
137
|
}.merge(options)
|
80
138
|
)
|
81
139
|
r.on_complete do |response|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
raise Error::Unauthorized
|
87
|
-
when 0
|
88
|
-
raise Error::ServerError, "Connection error: #{response.return_code}"
|
89
|
-
when 400...600
|
90
|
-
j = Oj.load(response.body)
|
91
|
-
code = j.dig('error', 'code')
|
92
|
-
error_class = case code
|
93
|
-
when 'invalid_input' then Error::InvalidInput
|
94
|
-
when 'forbidden' then Error::Forbidden
|
95
|
-
when 'locked' then Error::Locked
|
96
|
-
when 'not_found' then Error::NotFound
|
97
|
-
when 'rate_limit_exceeded' then Error::RateLimitExceeded
|
98
|
-
when 'resource_unavailable' then Error::ResourceUnavilable
|
99
|
-
when 'service_error' then Error::ServiceError
|
100
|
-
when 'uniqueness_error' then Error::UniquenessError
|
101
|
-
else
|
102
|
-
Error::ServerError
|
103
|
-
end
|
104
|
-
raise error_class, j.dig('error', 'message')
|
105
|
-
end
|
140
|
+
response.extend(TyphoeusExt)
|
141
|
+
response.attributes = hcloud_attributes
|
142
|
+
response.context.client = self
|
143
|
+
response.check_for_error unless response.request.hydra
|
106
144
|
end
|
107
145
|
r
|
108
146
|
end
|