Skip to content

Commit 04d3013

Browse files
author
Stefan Koch
authored
Merge pull request #60 from aufziehvogel/30-complete-resources
add missing features to existing resources
2 parents 5a5857e + 8b22d07 commit 04d3013

32 files changed

Lines changed: 641 additions & 433 deletions

lib/hcloud.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module Hcloud
1212
autoload :TyphoeusExt, 'hcloud/typhoeus_ext'
1313
autoload :AbstractResource, 'hcloud/abstract_resource'
1414
autoload :EntryLoader, 'hcloud/entry_loader'
15+
autoload :ResourceLoader, 'hcloud/resource_loader'
1516

1617
autoload :Server, 'hcloud/server'
1718
autoload :ServerResource, 'hcloud/server_resource'

lib/hcloud/entry_loader.rb

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -223,49 +223,17 @@ def _update_attribute(key, value)
223223
instance_variable_set("@#{key}", value)
224224
end
225225

226-
# rubocop: disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/AbcSize
227226
def _load(resource)
228227
return if resource.nil?
229228

230229
@_attributes = {}.with_indifferent_access
231230

232-
resource.each do |key, value|
233-
definition = self.class.schema[key]
234-
235-
if definition == :time
236-
_update_attribute(key, value ? Time.parse(value) : nil)
237-
next
238-
end
239-
240-
if definition.is_a?(Class) && definition.include?(EntryLoader)
241-
_update_attribute(key, value ? definition.new(client, value) : nil)
242-
next
243-
end
244-
245-
# if schema definition is [Class]
246-
if definition.is_a?(Array) && definition.first.include?(EntryLoader)
247-
248-
# just set attribute to an empty array if value is no array or empty
249-
if !value.is_a?(Array) || value.empty?
250-
_update_attribute(key, [])
251-
next
252-
end
253-
254-
if value.first.is_a?(Integer)
255-
# If value is an integer, this is the id of an object which's class can be
256-
# retreived from definition. Load a future object that can on access retreive the
257-
# data from the api and convert it to a proper object.
258-
_update_attribute(key, value.map { |id| Future.new(client, definition.first, id) })
259-
else
260-
# Otherwise the value *is* the content of the object
261-
_update_attribute(key, value.map { |item| definition.first.new(client, item) })
262-
end
263-
next
264-
end
231+
loader = Hcloud::ResourceLoader.new(self.class.schema, client: client)
232+
loaded_data = loader.load(resource)
265233

234+
loaded_data.each do |key, value|
266235
_update_attribute(key, value.is_a?(Hash) ? value.with_indifferent_access : value)
267236
end
268237
end
269-
# rubocop: enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/AbcSize
270238
end
271239
end

lib/hcloud/floating_ip.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class FloatingIP
1212
)
1313

1414
protectable :delete
15-
updatable :description
15+
updatable :name, :description
1616
destructible
1717

1818
has_actions

lib/hcloud/floating_ip_resource.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def [](arg)
1313
end
1414
end
1515

16-
def create(type:, server: nil, home_location: nil, description: nil, labels: {})
16+
def create(type:, name: nil, server: nil, home_location: nil, description: nil, labels: {})
1717
raise Hcloud::Error::InvalidInput, 'no type given' if type.blank?
1818
if server.nil? && home_location.nil?
1919
raise Hcloud::Error::InvalidInput, 'either server or home_location must be given'

lib/hcloud/future.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44

55
module Hcloud
66
class Future < Delegator
7+
attr_reader :raw_data
8+
79
# rubocop: disable Lint/MissingSuper
8-
def initialize(client, target_class, id)
10+
def initialize(client, target_class, id, raw_data: nil)
911
@target_class = target_class
1012
@id = id
13+
@raw_data = raw_data
1114
@__client = client
1215
end
1316
# rubocop: enable Lint/MissingSuper

lib/hcloud/image.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ class Image
1515
updatable :description, :type
1616
destructible
1717

18+
has_actions
19+
1820
def to_snapshot
1921
update(type: 'snapshot')
2022
end

lib/hcloud/image_resource.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
module Hcloud
44
class ImageResource < AbstractResource
5-
filter_attributes :type, :bound_to, :name, :label_selector
5+
filter_attributes :type, :bound_to, :name, :label_selector, :status, :include_deprecated
66

77
bind_to Image
88

lib/hcloud/network.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,11 @@ def del_route(destination:, gateway:)
4040

4141
prepare_request('actions/delete_route', j: COLLECT_ARGS.call(__method__, binding))
4242
end
43+
44+
def change_ip_range(ip_range:)
45+
raise Hcloud::Error::InvalidInput, 'no ip_range given' if ip_range.blank?
46+
47+
prepare_request('actions/change_ip_range', j: COLLECT_ARGS.call(__method__, binding))
48+
end
4349
end
4450
end

lib/hcloud/placement_group_resource.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
module Hcloud
44
class PlacementGroupResource < AbstractResource
5-
filter_attributes :type, :name
5+
filter_attributes :type, :name, :label_selector
66

77
bind_to PlacementGroup
88

lib/hcloud/resource_loader.rb

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# frozen_string_literal: true
2+
3+
require 'time'
4+
5+
module Hcloud
6+
class ResourceLoader
7+
def initialize(schema, client:)
8+
@schema = schema
9+
@client = client
10+
end
11+
12+
def load(data)
13+
load_with_schema(@schema, data)
14+
end
15+
16+
private
17+
18+
def load_with_schema(schema, data)
19+
if schema.respond_to?(:call)
20+
schema.call(data, @client)
21+
elsif schema.is_a?(Array) && schema.count.positive? && data.is_a?(Array)
22+
load_array(schema, data)
23+
elsif schema.is_a?(Hash) && data.is_a?(Hash)
24+
load_hash(schema, data)
25+
else
26+
load_single_item(schema, data)
27+
end
28+
end
29+
30+
def load_array(schema, data)
31+
data.map do |item|
32+
load_with_schema(schema[0], item)
33+
end
34+
end
35+
36+
def load_hash(schema, data)
37+
data.map do |key, value|
38+
[key, load_with_schema(schema[key], value)]
39+
end.to_h
40+
end
41+
42+
def load_single_item(definition, value)
43+
if definition == :time
44+
return value ? Time.parse(value) : nil
45+
end
46+
47+
if definition.is_a?(Class) && definition.include?(EntryLoader)
48+
return if value.nil?
49+
50+
# If value is an integer, this is the id of an object which's class can be
51+
# retreived from definition. Load a future object that can on access retreive the
52+
# data from the api and convert it to a proper object.
53+
return Future.new(@client, definition, value) if value.is_a?(Integer)
54+
55+
# Otherwise the value *is* the content of the object
56+
return definition.new(@client, value)
57+
end
58+
59+
value
60+
end
61+
end
62+
end

0 commit comments

Comments
 (0)