hcloud 1.1.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/hash/keys'
4
+
5
+ module Hcloud
6
+ class LoadBalancer
7
+ require 'hcloud/load_balancer_resource'
8
+
9
+ include EntryLoader
10
+
11
+ schema(
12
+ location: Location,
13
+ load_balancer_type: LoadBalancerType,
14
+ created: :time
15
+ )
16
+
17
+ protectable :delete
18
+ updatable :name
19
+ destructible
20
+
21
+ has_metrics
22
+ has_actions
23
+
24
+ %w[enable_public_interface disable_public_interface].each do |action|
25
+ define_method(action) do
26
+ prepare_request("actions/#{action}", method: :post)
27
+ end
28
+ end
29
+
30
+ def attach_to_network(network:, ip: nil)
31
+ raise Hcloud::Error::InvalidInput, 'no network given' if network.nil?
32
+
33
+ prepare_request('actions/attach_to_network', j: COLLECT_ARGS.call(__method__, binding))
34
+ end
35
+
36
+ def detach_from_network(network:)
37
+ raise Hcloud::Error::InvalidInput, 'no network given' if network.nil?
38
+
39
+ prepare_request('actions/detach_from_network', j: COLLECT_ARGS.call(__method__, binding))
40
+ end
41
+
42
+ def change_dns_ptr(ip:, dns_ptr:)
43
+ raise Hcloud::Error::InvalidInput, 'no IP given' if ip.blank?
44
+ raise Hcloud::Error::InvalidInput, 'no dns_ptr given' if dns_ptr.blank?
45
+
46
+ prepare_request('actions/change_dns_ptr', j: COLLECT_ARGS.call(__method__, binding))
47
+ end
48
+
49
+ def change_type(load_balancer_type:)
50
+ raise Hcloud::Error::InvalidInput, 'no type given' if load_balancer_type.blank?
51
+
52
+ prepare_request('actions/change_type', j: COLLECT_ARGS.call(__method__, binding))
53
+ end
54
+
55
+ def change_algorithm(type:)
56
+ raise Hcloud::Error::InvalidInput, 'no type given' if type.blank?
57
+
58
+ prepare_request('actions/change_algorithm', j: COLLECT_ARGS.call(__method__, binding))
59
+ end
60
+
61
+ def add_service(
62
+ protocol:, listen_port:, destination_port:, health_check:, proxyprotocol:, http: nil
63
+ )
64
+ validate_service_input(
65
+ protocol: protocol,
66
+ listen_port: listen_port,
67
+ destination_port: destination_port,
68
+ health_check: health_check,
69
+ proxyprotocol: proxyprotocol
70
+ )
71
+
72
+ prepare_request('actions/add_service', j: COLLECT_ARGS.call(__method__, binding))
73
+ end
74
+
75
+ def update_service(
76
+ protocol:, listen_port:, destination_port:, health_check:, proxyprotocol:, http: nil
77
+ )
78
+ validate_service_input(
79
+ protocol: protocol,
80
+ listen_port: listen_port,
81
+ destination_port: destination_port,
82
+ health_check: health_check,
83
+ proxyprotocol: proxyprotocol
84
+ )
85
+
86
+ prepare_request('actions/update_service', j: COLLECT_ARGS.call(__method__, binding))
87
+ end
88
+
89
+ def delete_service(listen_port:)
90
+ raise Hcloud::Error::InvalidInput, 'no listen_port given' if listen_port.nil?
91
+
92
+ prepare_request('actions/delete_service', j: COLLECT_ARGS.call(__method__, binding))
93
+ end
94
+
95
+ def add_target(type:, server: nil, label_selector: nil, ip: nil, use_private_ip: false)
96
+ validate_target_input(
97
+ type: type, server: server, label_selector: label_selector, ip: ip
98
+ )
99
+
100
+ prepare_request('actions/add_target', j: COLLECT_ARGS.call(__method__, binding))
101
+ end
102
+
103
+ def remove_target(type:, server: nil, label_selector: nil, ip: nil)
104
+ validate_target_input(
105
+ type: type, server: server, label_selector: label_selector, ip: ip
106
+ )
107
+
108
+ prepare_request('actions/remove_target', j: COLLECT_ARGS.call(__method__, binding))
109
+ end
110
+
111
+ private
112
+
113
+ def validate_service_input(
114
+ protocol:, listen_port:, destination_port:, health_check:, proxyprotocol:
115
+ )
116
+ raise Hcloud::Error::InvalidInput, 'no protocol given' if protocol.blank?
117
+ raise Hcloud::Error::InvalidInput, 'no listen_port given' if listen_port.nil?
118
+ raise Hcloud::Error::InvalidInput, 'no destination_port given' if destination_port.nil?
119
+ raise Hcloud::Error::InvalidInput, 'no health_check given' if health_check.nil?
120
+ raise Hcloud::Error::InvalidInput, 'no proxyprotocol given' if proxyprotocol.nil?
121
+ end
122
+
123
+ def validate_target_input(type:, server: nil, label_selector: nil, ip: nil)
124
+ raise Hcloud::Error::InvalidInput, 'no type given' if type.nil?
125
+
126
+ case type.to_sym
127
+ when :server
128
+ raise Hcloud::Error::InvalidInput, 'invalid server given' unless server.to_h.key?(:id)
129
+ when :ip
130
+ raise Hcloud::Error::InvalidInput, 'no IP given' if ip.blank?
131
+ when :label_selector
132
+ unless label_selector.to_h.key?(:selector)
133
+ raise Hcloud::Error::InvalidInput, 'invalid label_selector given'
134
+ end
135
+ else
136
+ raise Hcloud::Error::InvalidInput, 'invalid type given'
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hcloud
4
+ class LoadBalancerResource < AbstractResource
5
+ filter_attributes :name, :label_selector
6
+
7
+ bind_to LoadBalancer
8
+
9
+ def [](arg)
10
+ case arg
11
+ when Integer then find_by(id: arg)
12
+ when String then find_by(name: arg)
13
+ end
14
+ end
15
+
16
+ def create(
17
+ name:, load_balancer_type:, algorithm:, location: nil, network_zone: nil,
18
+ network: nil, public_interface: nil, services: nil, targets: nil,
19
+ labels: {}
20
+ )
21
+ raise Hcloud::Error::InvalidInput, 'no name given' if name.blank?
22
+ raise Hcloud::Error::InvalidInput, 'no type given' if load_balancer_type.blank?
23
+ if !algorithm.to_h.key?(:type) || algorithm[:type].blank?
24
+ raise Hcloud::Error::InvalidInput, 'invalid algorithm given'
25
+ end
26
+ if location.blank? && network_zone.blank?
27
+ raise Hcloud::Error::InvalidInput, 'either location or network_zone must be given'
28
+ end
29
+
30
+ prepare_request(
31
+ 'load_balancers', j: COLLECT_ARGS.call(__method__, binding),
32
+ expected_code: 201
33
+ ) do |response|
34
+ action = Action.new(client, response[:action]) if response[:action]
35
+ [action, LoadBalancer.new(client, response[:load_balancer])]
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hcloud
4
+ class LoadBalancerType
5
+ require 'hcloud/load_balancer_type_resource'
6
+
7
+ include EntryLoader
8
+
9
+ schema(
10
+ deprecated: :time
11
+ )
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hcloud
4
+ class LoadBalancerTypeResource < AbstractResource
5
+ filter_attributes :name
6
+
7
+ bind_to LoadBalancerType
8
+
9
+ def [](arg)
10
+ case arg
11
+ when Integer then find_by(id: arg)
12
+ when String then find_by(name: arg)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -15,19 +15,36 @@ module Hcloud
15
15
  has_actions
16
16
 
17
17
  def add_subnet(type:, network_zone:, ip_range: nil)
18
+ raise Hcloud::Error::InvalidInput, 'no type given' if type.blank?
19
+ raise Hcloud::Error::InvalidInput, 'no network_zone given' if network_zone.blank?
20
+
18
21
  prepare_request('actions/add_subnet', j: COLLECT_ARGS.call(__method__, binding))
19
22
  end
20
23
 
21
24
  def del_subnet(ip_range:)
25
+ raise Hcloud::Error::InvalidInput, 'no ip_range given' if ip_range.blank?
26
+
22
27
  prepare_request('actions/delete_subnet', j: COLLECT_ARGS.call(__method__, binding))
23
28
  end
24
29
 
25
30
  def add_route(destination:, gateway:)
31
+ raise Hcloud::Error::InvalidInput, 'no destination given' if destination.blank?
32
+ raise Hcloud::Error::InvalidInput, 'no gateway given' if gateway.blank?
33
+
26
34
  prepare_request('actions/add_route', j: COLLECT_ARGS.call(__method__, binding))
27
35
  end
28
36
 
29
37
  def del_route(destination:, gateway:)
38
+ raise Hcloud::Error::InvalidInput, 'no destination given' if destination.blank?
39
+ raise Hcloud::Error::InvalidInput, 'no gateway given' if gateway.blank?
40
+
30
41
  prepare_request('actions/delete_route', j: COLLECT_ARGS.call(__method__, binding))
31
42
  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
32
49
  end
33
50
  end
@@ -14,6 +14,9 @@ module Hcloud
14
14
  end
15
15
 
16
16
  def create(name:, ip_range:, subnets: nil, routes: nil, labels: {})
17
+ raise Hcloud::Error::InvalidInput, 'no name given' if name.blank?
18
+ raise Hcloud::Error::InvalidInput, 'no IP range given' if ip_range.blank?
19
+
17
20
  prepare_request(
18
21
  'networks', j: COLLECT_ARGS.call(__method__, binding),
19
22
  expected_code: 201
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hcloud
4
+ class PlacementGroup
5
+ require 'hcloud/placement_group_resource'
6
+
7
+ include EntryLoader
8
+
9
+ schema(
10
+ created: :time
11
+ )
12
+
13
+ updatable :name
14
+ destructible
15
+ end
16
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hcloud
4
+ class PlacementGroupResource < AbstractResource
5
+ filter_attributes :type, :name, :label_selector
6
+
7
+ bind_to PlacementGroup
8
+
9
+ def [](arg)
10
+ return find_by(name: arg) if arg.is_a?(String)
11
+
12
+ super
13
+ end
14
+
15
+ # currently only spread is available
16
+ def create(name:, type: 'spread', labels: {})
17
+ if type.to_s != 'spread'
18
+ raise Hcloud::Error::InvalidInput, "invalid type #{type.inspect}, only 'spread' is allowed"
19
+ end
20
+ raise Hcloud::Error::InvalidInput, 'no name given' if name.blank?
21
+
22
+ prepare_request(
23
+ 'placement_groups', j: COLLECT_ARGS.call(__method__, binding),
24
+ expected_code: 201
25
+ ) do |response|
26
+ PlacementGroup.new(client, response.parsed_json[:placement_group])
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hcloud
4
+ class PrimaryIP
5
+ require 'hcloud/primary_ip_resource'
6
+
7
+ include EntryLoader
8
+
9
+ schema(
10
+ datacenter: Datacenter,
11
+ created: :time
12
+ )
13
+
14
+ protectable :delete
15
+ updatable :name, :auto_delete
16
+ destructible
17
+
18
+ def assign(assignee_id:, assignee_type: 'server')
19
+ raise Hcloud::Error::InvalidInput, 'no assignee_id given' if assignee_id.nil?
20
+ raise Hcloud::Error::InvalidInput, 'no assignee_type given' if assignee_type.nil?
21
+
22
+ prepare_request('actions/assign', j: COLLECT_ARGS.call(__method__, binding))
23
+ end
24
+
25
+ def unassign
26
+ prepare_request('actions/unassign', method: :post)
27
+ end
28
+
29
+ def change_dns_ptr(ip:, dns_ptr:)
30
+ raise Hcloud::Error::InvalidInput, 'no IP given' if ip.blank?
31
+
32
+ prepare_request('actions/change_dns_ptr', j: { ip: ip, dns_ptr: dns_ptr })
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hcloud
4
+ class PrimaryIPResource < AbstractResource
5
+ filter_attributes :name, :label_selector, :ip
6
+
7
+ bind_to PrimaryIP
8
+
9
+ def [](arg)
10
+ case arg
11
+ when Integer then find_by(id: arg)
12
+ when String then find_by(name: arg)
13
+ end
14
+ end
15
+
16
+ def create(
17
+ name:,
18
+ type:,
19
+ assignee_id: nil,
20
+ assignee_type: 'server',
21
+ datacenter: nil,
22
+ auto_delete: nil,
23
+ labels: {}
24
+ )
25
+ raise Hcloud::Error::InvalidInput, 'no name given' if name.blank?
26
+
27
+ unless %w[ipv4 ipv6].include?(type.to_s)
28
+ raise Hcloud::Error::InvalidInput, 'invalid type given'
29
+ end
30
+
31
+ raise Hcloud::Error::InvalidInput, 'no assignee_type given' if assignee_type.blank?
32
+
33
+ if assignee_id.nil? && datacenter.nil?
34
+ raise Hcloud::Error::InvalidInput, 'either assignee_id or datacenter must be given'
35
+ end
36
+
37
+ prepare_request(
38
+ 'primary_ips', j: COLLECT_ARGS.call(__method__, binding),
39
+ expected_code: 201
40
+ ) do |response|
41
+ action = Action.new(client, response[:action]) if response[:action]
42
+ [action, PrimaryIP.new(client, response[:primary_ip])]
43
+ end
44
+ end
45
+ end
46
+ end
@@ -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
data/lib/hcloud/server.rb CHANGED
@@ -12,7 +12,24 @@ module Hcloud
12
12
  datacenter: Datacenter,
13
13
  image: Image,
14
14
  iso: Iso,
15
+ load_balancers: [LoadBalancer],
16
+ placement_group: PlacementGroup,
15
17
  private_net: [Network],
18
+ public_net: {
19
+ ipv4: lambda do |data, client|
20
+ Future.new(client, PrimaryIP, data[:id]) if data.to_h[:id].is_a?(Integer)
21
+ end,
22
+ ipv6: lambda do |data, client|
23
+ Future.new(client, PrimaryIP, data[:id]) if data.to_h[:id].is_a?(Integer)
24
+ end,
25
+ floating_ips: [FloatingIP],
26
+ firewalls: [
27
+ lambda do |data, client|
28
+ Future.new(client, Firewall, data[:id], raw_data: data) if data.to_h[:id].is_a?(Integer)
29
+ end
30
+ ]
31
+ # firewalls: [{ id: Firewall }]
32
+ },
16
33
  volumes: [Volume]
17
34
  )
18
35
 
@@ -21,6 +38,7 @@ module Hcloud
21
38
  destructible
22
39
 
23
40
  has_actions
41
+ has_metrics
24
42
 
25
43
  def enable_rescue(type: 'linux64', ssh_keys: [])
26
44
  query = COLLECT_ARGS.call(__method__, binding)
@@ -37,10 +55,15 @@ module Hcloud
37
55
  end
38
56
 
39
57
  def rebuild(image:)
58
+ raise Hcloud::Error::InvalidInput, 'no image given' if image.blank?
59
+
40
60
  prepare_request('actions/rebuild', j: { image: image }) { |j| j[:root_password] }
41
61
  end
42
62
 
43
- def change_type(server_type:, upgrade_disk: nil)
63
+ def change_type(server_type:, upgrade_disk:)
64
+ raise Hcloud::Error::InvalidInput, 'no server_type given' if server_type.blank?
65
+ raise Hcloud::Error::InvalidInput, 'no upgrade_disk given' if upgrade_disk.nil?
66
+
44
67
  prepare_request('actions/change_type', j: COLLECT_ARGS.call(__method__, binding))
45
68
  end
46
69
 
@@ -51,21 +74,47 @@ module Hcloud
51
74
  end
52
75
 
53
76
  def attach_iso(iso:)
77
+ raise Hcloud::Error::InvalidInput, 'no iso given' if iso.blank?
78
+
54
79
  prepare_request('actions/attach_iso', j: { iso: iso })
55
80
  end
56
81
 
57
82
  def attach_to_network(network:, ip: nil, alias_ips: nil)
83
+ raise Hcloud::Error::InvalidInput, 'no network given' if network.nil?
84
+
58
85
  prepare_request('actions/attach_to_network', j: COLLECT_ARGS.call(__method__, binding))
59
86
  end
60
87
 
61
88
  def detach_from_network(network:)
89
+ raise Hcloud::Error::InvalidInput, 'no network given' if network.nil?
90
+
62
91
  prepare_request('actions/detach_from_network', j: { network: network })
63
92
  end
64
93
 
94
+ def add_to_placement_group(placement_group:)
95
+ raise Hcloud::Error::InvalidInput, 'no placement_group given' if placement_group.nil?
96
+
97
+ prepare_request('actions/add_to_placement_group', j: COLLECT_ARGS.call(__method__, binding))
98
+ end
99
+
100
+ def change_alias_ips(alias_ips:, network:)
101
+ raise Hcloud::Error::InvalidInput, 'no alias_ips given' if alias_ips.to_a.count.zero?
102
+ raise Hcloud::Error::InvalidInput, 'no network given' if network.nil?
103
+
104
+ prepare_request('actions/change_alias_ips', j: COLLECT_ARGS.call(__method__, binding))
105
+ end
106
+
107
+ def change_dns_ptr(ip:, dns_ptr:)
108
+ raise Hcloud::Error::InvalidInput, 'no IP given' if ip.blank?
109
+ raise Hcloud::Error::InvalidInput, 'no dns_ptr given' if dns_ptr.blank?
110
+
111
+ prepare_request('actions/change_dns_ptr', j: COLLECT_ARGS.call(__method__, binding))
112
+ end
113
+
65
114
  %w[
66
115
  poweron poweroff shutdown reboot reset
67
116
  disable_rescue disable_backup detach_iso
68
- request_console
117
+ request_console remove_from_placement_group
69
118
  ].each do |action|
70
119
  define_method(action) do
71
120
  prepare_request("actions/#{action}", method: :post)
@@ -12,15 +12,23 @@ module Hcloud
12
12
  location: nil,
13
13
  start_after_create: nil,
14
14
  ssh_keys: [],
15
+ public_net: nil,
16
+ firewalls: nil,
15
17
  networks: [],
18
+ placement_group: nil,
16
19
  user_data: nil,
20
+ volumes: nil,
21
+ automount: nil,
17
22
  labels: {})
18
23
  prepare_request('servers', j: COLLECT_ARGS.call(__method__, binding),
19
24
  expected_code: 201) do |response|
20
25
  [
21
26
  Action.new(client, response.parsed_json[:action]),
22
27
  Server.new(client, response.parsed_json[:server]),
23
- response.parsed_json[:root_password]
28
+ response.parsed_json[:root_password],
29
+ response.parsed_json[:next_actions].to_a.map do |action|
30
+ Action.new(client, action)
31
+ end
24
32
  ]
25
33
  end
26
34
  end
@@ -6,6 +6,10 @@ module Hcloud
6
6
 
7
7
  include EntryLoader
8
8
 
9
+ schema(
10
+ created: :time
11
+ )
12
+
9
13
  updatable :name
10
14
  destructible
11
15
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Hcloud
4
4
  class SSHKeyResource < AbstractResource
5
- filter_attributes :name, :label_selector
5
+ filter_attributes :name, :label_selector, :fingerprint
6
6
 
7
7
  def [](arg)
8
8
  case arg
@@ -12,6 +12,12 @@ module Hcloud
12
12
  end
13
13
 
14
14
  def create(name:, public_key:, labels: {})
15
+ raise Hcloud::Error::InvalidInput, 'no name given' if name.blank?
16
+
17
+ unless public_key.to_s.starts_with?('ssh')
18
+ raise Hcloud::Error::InvalidInput, 'no valid SSH key given'
19
+ end
20
+
15
21
  prepare_request(
16
22
  'ssh_keys', j: COLLECT_ARGS.call(__method__, binding),
17
23
  expected_code: 201
@@ -30,7 +30,7 @@ module Hcloud
30
30
  def parsed_json
31
31
  return {} if code == 204
32
32
 
33
- @parsed_json ||= Oj.load(body, symbol_keys: true).tap do |json|
33
+ @parsed_json ||= Oj.load(body, symbol_keys: true, mode: :compat).tap do |json|
34
34
  next unless request.hydra
35
35
 
36
36
  check_for_error(
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hcloud
4
- VERSION = '1.1.0'
4
+ VERSION = '1.3.0'
5
5
  end
data/lib/hcloud/volume.rb CHANGED
@@ -17,7 +17,9 @@ module Hcloud
17
17
 
18
18
  has_actions
19
19
 
20
- def attach(server:, automount:)
20
+ def attach(server:, automount: nil)
21
+ raise Hcloud::Error::InvalidInput, 'no server given' if server.nil?
22
+
21
23
  prepare_request('actions/attach', j: COLLECT_ARGS.call(__method__, binding))
22
24
  end
23
25
 
@@ -26,6 +28,8 @@ module Hcloud
26
28
  end
27
29
 
28
30
  def resize(size:)
31
+ raise Hcloud::Error::InvalidInput, 'invalid size given' unless size.to_i > self.size
32
+
29
33
  prepare_request('actions/resize', j: COLLECT_ARGS.call(__method__, binding))
30
34
  end
31
35
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Hcloud
4
4
  class VolumeResource < AbstractResource
5
- filter_attributes :name, :label_selector
5
+ filter_attributes :name, :label_selector, :status
6
6
 
7
7
  def [](arg)
8
8
  case arg
@@ -12,6 +12,12 @@ module Hcloud
12
12
  end
13
13
 
14
14
  def create(size:, name:, automount: nil, format: nil, location: nil, server: nil, labels: {})
15
+ raise Hcloud::Error::InvalidInput, 'no name given' if name.blank?
16
+ raise Hcloud::Error::InvalidInput, 'invalid size given' unless size.to_i >= 10
17
+ if location.blank? && server.nil?
18
+ raise Hcloud::Error::InvalidInput, 'location or server must be given'
19
+ end
20
+
15
21
  prepare_request(
16
22
  'volumes', j: COLLECT_ARGS.call(__method__, binding),
17
23
  expected_code: 201