hcloud 1.1.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +8 -1
- data/CHANGELOG.md +52 -0
- data/Gemfile.lock +66 -57
- data/hcloud.gemspec +1 -2
- data/lib/hcloud/abstract_resource.rb +1 -1
- data/lib/hcloud/certificate.rb +22 -0
- data/lib/hcloud/certificate_resource.rb +43 -0
- data/lib/hcloud/client.rb +20 -0
- data/lib/hcloud/entry_loader.rb +24 -35
- data/lib/hcloud/firewall.rb +12 -1
- data/lib/hcloud/firewall_resource.rb +8 -1
- data/lib/hcloud/floating_ip.rb +5 -1
- data/lib/hcloud/floating_ip_resource.rb +6 -1
- data/lib/hcloud/future.rb +4 -1
- data/lib/hcloud/image.rb +2 -0
- data/lib/hcloud/image_resource.rb +1 -1
- data/lib/hcloud/load_balancer.rb +140 -0
- data/lib/hcloud/load_balancer_resource.rb +39 -0
- data/lib/hcloud/load_balancer_type.rb +13 -0
- data/lib/hcloud/load_balancer_type_resource.rb +16 -0
- data/lib/hcloud/network.rb +17 -0
- data/lib/hcloud/network_resource.rb +3 -0
- data/lib/hcloud/placement_group.rb +16 -0
- data/lib/hcloud/placement_group_resource.rb +30 -0
- data/lib/hcloud/primary_ip.rb +35 -0
- data/lib/hcloud/primary_ip_resource.rb +46 -0
- data/lib/hcloud/resource_loader.rb +62 -0
- data/lib/hcloud/server.rb +51 -2
- data/lib/hcloud/server_resource.rb +9 -1
- data/lib/hcloud/ssh_key.rb +4 -0
- data/lib/hcloud/ssh_key_resource.rb +7 -1
- data/lib/hcloud/typhoeus_ext.rb +1 -1
- data/lib/hcloud/version.rb +1 -1
- data/lib/hcloud/volume.rb +5 -1
- data/lib/hcloud/volume_resource.rb +7 -1
- data/lib/hcloud.rb +18 -0
- metadata +19 -23
- data/Rakefile +0 -4
@@ -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,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
|
data/lib/hcloud/network.rb
CHANGED
@@ -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,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:
|
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
|
data/lib/hcloud/ssh_key.rb
CHANGED
@@ -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
|
data/lib/hcloud/typhoeus_ext.rb
CHANGED
@@ -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(
|
data/lib/hcloud/version.rb
CHANGED
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
|