hetznercloud 3.0.0 → 4.1.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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +105 -6
  3. data/README.md +49 -32
  4. data/lib/hcloud/action_collection.rb +2 -2
  5. data/lib/hcloud/client.rb +28 -2
  6. data/lib/hcloud/collection.rb +10 -2
  7. data/lib/hcloud/concerns/actionable.rb +1 -1
  8. data/lib/hcloud/concerns/creatable.rb +21 -6
  9. data/lib/hcloud/concerns/deletable.rb +8 -3
  10. data/lib/hcloud/concerns/meterable.rb +1 -1
  11. data/lib/hcloud/concerns/queryable.rb +3 -3
  12. data/lib/hcloud/concerns/subresource.rb +62 -0
  13. data/lib/hcloud/concerns/updatable.rb +1 -1
  14. data/lib/hcloud/entities/storage_box_access_settings.rb +17 -0
  15. data/lib/hcloud/entities/storage_box_price.rb +10 -0
  16. data/lib/hcloud/entities/storage_box_snapshot_plan.rb +11 -0
  17. data/lib/hcloud/entities/storage_box_snapshot_stats.rb +8 -0
  18. data/lib/hcloud/entities/storage_box_stats.rb +9 -0
  19. data/lib/hcloud/entities/storage_box_subaccount_access_settings.rb +19 -0
  20. data/lib/hcloud/errors.rb +2 -1
  21. data/lib/hcloud/http.rb +4 -2
  22. data/lib/hcloud/resource.rb +1 -0
  23. data/lib/hcloud/resource_type.rb +10 -0
  24. data/lib/hcloud/resources/certificate.rb +1 -1
  25. data/lib/hcloud/resources/datacenter.rb +1 -1
  26. data/lib/hcloud/resources/firewall.rb +1 -1
  27. data/lib/hcloud/resources/floating_ip.rb +1 -1
  28. data/lib/hcloud/resources/load_balancer.rb +1 -1
  29. data/lib/hcloud/resources/network.rb +1 -1
  30. data/lib/hcloud/resources/placement_group.rb +1 -1
  31. data/lib/hcloud/resources/primary_ip.rb +1 -1
  32. data/lib/hcloud/resources/server.rb +1 -1
  33. data/lib/hcloud/resources/server_type.rb +1 -0
  34. data/lib/hcloud/resources/ssh_key.rb +1 -1
  35. data/lib/hcloud/resources/storage_box.rb +195 -0
  36. data/lib/hcloud/resources/storage_box_snapshot.rb +108 -0
  37. data/lib/hcloud/resources/storage_box_subaccount.rb +129 -0
  38. data/lib/hcloud/resources/storage_box_type.rb +43 -0
  39. data/lib/hcloud/resources/volume.rb +2 -2
  40. data/lib/hcloud/sub_collection.rb +79 -0
  41. data/lib/hcloud/version.rb +2 -2
  42. data/lib/http/features/compression.rb +1 -1
  43. data/lib/http/features/request/brotli_body.rb +1 -1
  44. data/lib/http/features/response/brotli_inflater.rb +1 -1
  45. data/lib/http/rate_limiter.rb +2 -0
  46. metadata +18 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79a6b89356738d96488c66c11fe1db0898ec7d49a3e9916860e8b181b0d81ad9
4
- data.tar.gz: c8fff383978d3f10d96997a4abe1cd25b03517d9aea0c95b332173cfaa18fe9b
3
+ metadata.gz: 0e9575422834c710e68322d4d3d9d738521d1a45d8924f90eee7b64da43e47ed
4
+ data.tar.gz: 4edab154b29f3c5d3a43d55bdf5d9282418d470105d272446283e564b2f3ee12
5
5
  SHA512:
6
- metadata.gz: 0375abf58d85d71138bfa68aa23e62d15f3e7a1230d7d7c175925f141138e256d6dbb0e4518995130bfab9cc8990ea3362a367d64f416a5d45adbcc0a8459257
7
- data.tar.gz: 42aeba6192a1b77f2b7f123256ef6eb331faa28bf0fe28ccd50be4258576cef4408ff572d676342584a41104e5daedb238bf4727df1ab54f64c555e1fc3c0e70
6
+ metadata.gz: 5009c504916ca8404c11bd855377e101121fd77e7a53517f4f1b740d540ac36815a47b710429520ddb93458db29e43311444655196931f6a88c3c1dd7bd49461
7
+ data.tar.gz: 8af42a4fe808cd090033913f1bb5b3d73eca8066da3ace50e470df6355a90b93981e7fe6167679f7b877b572fb26c2d7b5772b3ac15bd633f0a844353ab343a8
data/CHANGELOG.md CHANGED
@@ -1,85 +1,176 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ ### Added
6
+
7
+ ### Changed
8
+
9
+ ### Removed
10
+
11
+ ### Fixed
12
+
13
+ ## HCloud v4.1.0 (2025-09-02)
14
+
15
+ ### Added
16
+
17
+ - Add `category` attribute to `ServerType`
18
+
19
+ ### Changed
20
+
21
+ - Allow certain `create` and `delete` methods to return a `HCloud::Action` instance instead of a resource, as returned by the API (e.g. Storage Box API)
22
+
23
+ ## HCloud v4.0.0 (2025-07-26)
24
+
25
+ ### Added
26
+
27
+ - Add `LoadBalancerPublicInterfaceDisabled` error class
28
+ - Implement Storage Boxes
29
+ - Implement Storage Box Types
30
+ - Implement Storage Box Subaccounts
31
+ - Implement Storage Box Subaccount actions
32
+
33
+ ### Changed
34
+
35
+ - Change `HCloud::Collection#where` interface: now accepts a string instead of a hash to allow for more complex queries
36
+ - For example: `HCloud::Server.where(label_selector: "env=prod,app!=web")`
37
+ - Cache total entries in `HCloud::Collection` when calling #count
38
+
39
+ ### Fixed
40
+
41
+ - Fix a zero division error in the rate limiter when rate limit headers are not set
42
+ - Fix an error in the error parsing code when the error details are not present
43
+
3
44
  ## HCloud v3.0.0 (2024-11-25)
4
45
 
5
- - Removed `included_traffic` attribute from `ServerType`
6
- - Removed `traffic` attribute from `Pricing`
46
+ ### Removed
47
+
48
+ - Remove `included_traffic` attribute from `ServerType`
49
+ - Remove `traffic` attribute from `Pricing`
7
50
 
8
51
  ## HCloud v2.2.1 (2024-08-30)
9
52
 
53
+ ### Changed
54
+
10
55
  - Add deprecation warning for `Pricing#floating_ip`
11
56
 
12
57
  ## HCloud v2.2.0 (2024-08-22)
13
58
 
59
+ ### Added
60
+
14
61
  - Add support for (de-)compression of HTTP requests
15
62
 
16
63
  ## HCloud v2.1.0 (2024-07-28)
17
64
 
65
+ ### Added
66
+
18
67
  - Add `included_traffic` attribute to `ServerType#prices` and `LoadBalancerType#prices`
19
68
  - Add `price_per_tb_traffic` attribute to `ServerType#prices` and `LoadBalancerType#prices`
69
+
70
+ ### Changed
71
+
20
72
  - Add deprecation warning for `Pricing#traffic`
21
73
  - Add deprecation warning for `ServerType#included_traffic`
74
+
75
+ ### Fixed
76
+
22
77
  - Fix crash on prices when using `Pricing` API
23
78
 
24
79
  ## HCloud v2.0.0 (2024-01-10)
25
80
 
81
+ ### Removed
82
+
26
83
  - Remove `deprecated` attribute from `ISO`
27
84
 
28
85
  ## HCloud v1.7.2 (2023-10-16)
29
86
 
87
+ ### Added
88
+
30
89
  - Add `deprecation` attribute to `ISO`
31
90
 
32
91
  ## HCloud v1.7.1 (2023-07-25)
33
92
 
93
+ ### Changed
94
+
34
95
  - Add deprecation warning for `HCloud::Action.all`
35
96
 
36
97
  ## HCloud v1.7.0 (2023-06-30)
37
98
 
99
+ ### Added
100
+
38
101
  - Add load balancer actions
39
102
 
40
103
  ## HCloud v1.6.1 (2023-06-22)
41
104
 
105
+ ### Added
106
+
42
107
  - Add `expose_routes_to_vswitch` attribute to `Network`
43
108
 
44
109
  ## HCloud v1.6.0 (2023-06-07)
45
110
 
111
+ ### Added
112
+
46
113
  - Add `deprecation` attribute to `ServerType`
114
+
115
+ ### Changed
116
+
47
117
  - Parse `private_net` attribute on `Server` as array
48
118
  - Parse `public_net.firewalls` attribute on `Server` as array of objects with status (not array of `Firewall`s)
49
119
 
50
120
  ## HCloud v1.5.4 (2023-05-17)
51
121
 
122
+ ### Changed
123
+
52
124
  - Allow defining attributes on the fly
53
125
 
54
126
  ## HCloud v1.5.3 (2023-05-09)
55
127
 
128
+ ### Added
129
+
56
130
  - Add `included_traffic` attribute to `ServerType`
57
131
 
58
132
  ## HCloud v1.5.2 (2023-04-22)
59
133
 
134
+ ### Added
135
+
60
136
  - Add `architecture` attribute to `Image` and `ISO`
61
137
 
62
138
  ## HCloud v1.5.1 (2023-04-20)
63
139
 
140
+ ### Added
141
+
64
142
  - Add `Unavailable` error class
65
143
  - Add `architecture` attribute to `ServerType`
66
144
 
67
145
  ## HCloud v1.5.0 (2023-02-01)
68
146
 
147
+ ### Added
148
+
69
149
  - Add pricing for Primary IPs
70
150
  - Add server Metadata resource
71
151
  - Add support for rate limits
72
- - `Action#resources` now returns a list of resources instead of a list of hashes
73
- - Separate server protection entity from other protection entity (only server protection includes `rebuild`)
74
152
  - Add shorthand methods for `.first`, `.last`, `.count`, `.where`, `.sort`, `.each`, and `.empty?` on resource
75
153
  - Add `label_selector:` argument to `HCloud::Collection`
76
154
 
155
+ ### Changed
156
+
157
+ - `Action#resources` now returns a list of resources instead of a list of hashes
158
+ - Separate server protection entity from other protection entity (only server protection includes `rebuild`)
159
+
77
160
  ## HCloud v1.4.0 (2023-01-22)
78
161
 
162
+ ### Added
163
+
79
164
  - Implemented Primary IPs
80
165
  - Implemented Primary IP Actions
81
- - Allow calling `#update` with additional attributes to be updated
166
+
167
+ ### Changed
168
+
82
169
  - Return the resource when calling `#create`, `#update` or `#delete`
170
+
171
+ ### Fixed
172
+
173
+ - Allow calling `#update` with additional attributes to be updated
83
174
  - Add additional primary IP mismatch errors:
84
175
  - `PrimaryIPAssigned`
85
176
  - `PrimaryIPDatacenterMismatch`
@@ -87,15 +178,21 @@
87
178
 
88
179
  ## HCloud v1.3.1 (2022-02-06)
89
180
 
90
- - Add missing `Server#user_data`
181
+ ### Added
182
+
183
+ - Add `user_data` attribute to `Server`
91
184
 
92
185
  ## HCloud v1.3.0 (2022-02-04)
93
186
 
187
+ ### Added
188
+
94
189
  - Implemented Load Balancers
95
190
  - Implemented Load Balancer Types
96
191
 
97
192
  ## HCloud v1.2.0 (2022-02-01)
98
193
 
194
+ ### Added
195
+
99
196
  - Implemented Networks
100
197
  - Implemented Network Actions
101
198
  - Implemented Pricing
@@ -104,6 +201,8 @@
104
201
 
105
202
  ## HCloud v1.1.0 (2022-01-30)
106
203
 
204
+ ### Added
205
+
107
206
  - Implemented Firewall Actions
108
207
 
109
208
  ## HCloud v1.0.0 (2022-01-16)
data/README.md CHANGED
@@ -69,36 +69,42 @@ It expects you to use it in a sane way.
69
69
 
70
70
  The following table lists the Hetzner Cloud API endpoints that are currently implemented.
71
71
 
72
- | Resource | State |
73
- |----------------------------------------------------------------|-----------------------|
74
- | [Actions](lib/hcloud/resources/action.rb) | Implemented |
75
- | [Certificates](lib/hcloud/resources/certificate.rb) | Implemented |
76
- | [Certificate Actions](lib/hcloud/resources/certificate.rb) | Implemented |
77
- | [Datacenters](lib/hcloud/resources/datacenter.rb) | Implemented |
78
- | [Firewalls](lib/hcloud/resources/firewall.rb) | Implemented |
79
- | [Firewall Actions](lib/hcloud/resources/firewall.rb) | Implemented |
80
- | [Floating IPs](lib/hcloud/resources/floating_ip.rb) | Implemented |
81
- | [Floating IP Actions](lib/hcloud/resources/floating_ip.rb) | Implemented |
82
- | [Images](lib/hcloud/resources/image.rb) | Implemented |
83
- | [Image Actions](lib/hcloud/resources/image.rb) | Implemented |
84
- | [ISOs](lib/hcloud/resources/iso.rb) | Implemented |
85
- | [Load Balancers](lib/hcloud/resources/load_balancer.rb) | Implemented |
86
- | [Load Balancer Actions](lib/hcloud/resources/load_balancer.rb) | Implemented |
87
- | [Load Balancer Types](lib/hcloud/resources/load_balancer.rb) | Implemented |
88
- | [Locations](lib/hcloud/resources/location.rb) | Implemented |
89
- | [Primary IPs](lib/hcloud/resources/primary_ip.rb) | Implemented |
90
- | [Primary IP Actions](lib/hcloud/resources/primary_ip.rb) | Implemented |
91
- | [Networks](lib/hcloud/resources/network.rb) | Implemented |
92
- | [Network Actions](lib/hcloud/resources/network.rb) | Implemented |
93
- | [Placement Groups](lib/hcloud/resources/placement_group.rb) | Implemented |
94
- | [Pricing](lib/hcloud/resources/pricing.rb) | Implemented |
95
- | [Servers](lib/hcloud/resources/server.rb) | Partially implemented |
96
- | [Server Actions](lib/hcloud/resources/server.rb) | Not implemented |
97
- | [Server Types](lib/hcloud/resources/server_type.rb) | Implemented |
98
- | [SSH Keys](lib/hcloud/resources/ssh_key.rb) | Implemented |
99
- | [Volumes](lib/hcloud/resources/volume.rb) | Implemented |
100
- | [Volume Actions](lib/hcloud/resources/volume.rb) | Implemented |
101
- | [Metadata](lib/hcloud/resources/metadata.rb) | Implemented |
72
+ | Resource | State |
73
+ |----------------------------------------------------------------------------------|-----------------------|
74
+ | [Actions](lib/hcloud/resources/action.rb) | Implemented |
75
+ | [Certificates](lib/hcloud/resources/certificate.rb) | Implemented |
76
+ | [Certificate Actions](lib/hcloud/resources/certificate.rb) | Implemented |
77
+ | [Datacenters](lib/hcloud/resources/datacenter.rb) | Implemented |
78
+ | [Firewalls](lib/hcloud/resources/firewall.rb) | Implemented |
79
+ | [Firewall Actions](lib/hcloud/resources/firewall.rb) | Implemented |
80
+ | [Floating IPs](lib/hcloud/resources/floating_ip.rb) | Implemented |
81
+ | [Floating IP Actions](lib/hcloud/resources/floating_ip.rb) | Implemented |
82
+ | [Images](lib/hcloud/resources/image.rb) | Implemented |
83
+ | [Image Actions](lib/hcloud/resources/image.rb) | Implemented |
84
+ | [ISOs](lib/hcloud/resources/iso.rb) | Implemented |
85
+ | [Load Balancers](lib/hcloud/resources/load_balancer.rb) | Implemented |
86
+ | [Load Balancer Actions](lib/hcloud/resources/load_balancer.rb) | Implemented |
87
+ | [Load Balancer Types](lib/hcloud/resources/load_balancer.rb) | Implemented |
88
+ | [Locations](lib/hcloud/resources/location.rb) | Implemented |
89
+ | [Primary IPs](lib/hcloud/resources/primary_ip.rb) | Implemented |
90
+ | [Primary IP Actions](lib/hcloud/resources/primary_ip.rb) | Implemented |
91
+ | [Networks](lib/hcloud/resources/network.rb) | Implemented |
92
+ | [Network Actions](lib/hcloud/resources/network.rb) | Implemented |
93
+ | [Placement Groups](lib/hcloud/resources/placement_group.rb) | Implemented |
94
+ | [Pricing](lib/hcloud/resources/pricing.rb) | Implemented |
95
+ | [Servers](lib/hcloud/resources/server.rb) | Partially implemented |
96
+ | [Server Actions](lib/hcloud/resources/server.rb) | Not implemented |
97
+ | [Server Types](lib/hcloud/resources/server_type.rb) | Implemented |
98
+ | [SSH Keys](lib/hcloud/resources/ssh_key.rb) | Implemented |
99
+ | [Storage Boxes](lib/hcloud/resources/storage_box.rb) | Implemented |
100
+ | [Storage Box Actions](lib/hcloud/resources/storage_box.rb) | Implemented |
101
+ | [Storage Box Types](lib/hcloud/resources/storage_box_type.rb) | Implemented |
102
+ | [Storage Box Subaccount](lib/hcloud/resources/storage_box_subaccount.rb) | Implemented |
103
+ | [Storage Box Subaccount Actions](lib/hcloud/resources/storage_box_subaccount.rb) | Implemented |
104
+ | [Storage Box Snapshot](lib/hcloud/resources/storage_box_snapshot.rb) | Implemented |
105
+ | [Volumes](lib/hcloud/resources/volume.rb) | Implemented |
106
+ | [Volume Actions](lib/hcloud/resources/volume.rb) | Implemented |
107
+ | [Metadata](lib/hcloud/resources/metadata.rb) | Implemented |
102
108
 
103
109
  ### Pagination
104
110
 
@@ -159,6 +165,13 @@ To use Brotli compression, you need to install the `brotli` gem (at least versio
159
165
  gem "brotli"
160
166
  ```
161
167
 
168
+ ## Storage boxes
169
+
170
+ Please note that storage boxes require a different API endpoint.
171
+ The endpoint for **storage boxes** is `https://api.hetzner.com/v1`.
172
+ The endpoint for **all other resources** is `https://api.hetzner.cloud/v1`.
173
+ The storage box endpoint is passed as an extra argument to the `HCloud::Client`, see [Endpoint](#endpoint) for more information.
174
+
162
175
  ## Testing
163
176
 
164
177
  ```ssh
@@ -186,10 +199,14 @@ When executing the test suite, set `LOG_LEVEL` environment variable to `debug` i
186
199
 
187
200
  ### Endpoint
188
201
 
189
- `HCloud::Client` also accepts an alternate endpoint:
202
+ `HCloud::Client` also accepts alternate endpoints:
190
203
 
191
204
  ```ruby
192
- client = HCloud::Client.new(access_token: "my_access_token", endpoint: "https://myproxy/v1")
205
+ client = HCloud::Client.new(
206
+ endpoint: "https://myproxy/v1",
207
+ storage_box_endpoint: "https://myproxy/storage-box/v1",
208
+ access_token: "my_access_token",
209
+ )
193
210
  ```
194
211
 
195
212
  ## Releasing
@@ -14,7 +14,7 @@ module HCloud
14
14
  def find(id)
15
15
  Action.new resource
16
16
  .client
17
- .get("/#{resource.resource_name.pluralize}/#{resource.id}/actions/#{id}")
17
+ .get("#{resource.resource_path}/#{resource.id}/actions/#{id}")
18
18
  .fetch(:action)
19
19
  end
20
20
 
@@ -23,7 +23,7 @@ module HCloud
23
23
  def all(params)
24
24
  response = resource
25
25
  .client
26
- .get("/#{resource.resource_name.pluralize}/#{resource.id}/actions", params)
26
+ .get("#{resource.resource_path}/#{resource.id}/actions", params)
27
27
 
28
28
  data = response
29
29
  .fetch(:actions)
data/lib/hcloud/client.rb CHANGED
@@ -21,17 +21,43 @@ module HCloud
21
21
 
22
22
  self.connection = NilConnection.new
23
23
 
24
- attr_reader :access_token, :endpoint, :logger, :rate_limit, :timeout, :compression
24
+ attr_reader :access_token,
25
+ :endpoint,
26
+ :storage_box_endpoint,
27
+ :logger,
28
+ :rate_limit,
29
+ :timeout,
30
+ :compression
25
31
 
26
- def initialize(access_token:, endpoint: "https://api.hetzner.cloud/v1", logger: Logger.new("/dev/null"), rate_limit: false, timeout: 10, compression: nil)
32
+ def initialize(
33
+ access_token:,
34
+ endpoint: "https://api.hetzner.cloud/v1",
35
+ storage_box_endpoint: "https://api.hetzner.com/v1",
36
+ logger: Logger.new(File::NULL),
37
+ rate_limit: false,
38
+ timeout: 10,
39
+ compression: nil
40
+ )
27
41
  @access_token = access_token
28
42
  @endpoint = endpoint
43
+ @storage_box_endpoint = storage_box_endpoint
29
44
  @logger = logger
30
45
  @rate_limit = rate_limit
31
46
  @timeout = timeout
32
47
  @compression = compression
33
48
  end
34
49
 
50
+ def storage_box_client
51
+ @storage_box_client ||= HCloud::Client.new(
52
+ access_token: access_token,
53
+ endpoint: storage_box_endpoint,
54
+ logger: logger,
55
+ rate_limit: rate_limit,
56
+ timeout: timeout,
57
+ compression: compression,
58
+ )
59
+ end
60
+
35
61
  delegate :get, :put, :post, :delete, to: :http
36
62
 
37
63
  private
@@ -56,13 +56,21 @@ module HCloud
56
56
 
57
57
  def count
58
58
  # Fetch total_entries if not present
59
- @count ||= total_entries || proc.call(params.merge(page: 1)).last.dig(:pagination, :total_entries)
59
+ @count ||= @total_entries ||= proc.call(params.merge(page: 1)).last.dig(:pagination, :total_entries) # rubocop:disable Naming/MemoizedInstanceVariableName
60
60
  end
61
61
 
62
62
  def empty?
63
63
  count.zero?
64
64
  end
65
65
 
66
+ def inspect
67
+ filters = filter_by.any? ? "filters: (#{filter_by.map { |k, v| "#{k} = #{v.inspect}" }.join(', ')})" : nil
68
+ sort = sort_by ? "sort: (#{sort_by.join(', ')})" : nil
69
+ label_selector = label_selector ? "labels_selector: (#{label_selector})" : nil
70
+
71
+ "#<#{self.class}#{[filters, sort, label_selector].compact.join(', ').presence&.prepend(' ')} page: #{page}, per_page: #{per_page}, total_entries: #{total_entries.inspect}>"
72
+ end
73
+
66
74
  delegate :[], :last, to: :to_a
67
75
 
68
76
  private
@@ -72,7 +80,7 @@ module HCloud
72
80
  page: page,
73
81
  per_page: per_page,
74
82
  sort: sort_by,
75
- label_selector: label_selector&.map { |k, v| "#{k}=#{v}" }&.join(","),
83
+ label_selector: label_selector,
76
84
  **filter_by,
77
85
  }
78
86
  end
@@ -23,7 +23,7 @@ module HCloud
23
23
  raise Errors::MissingIDError unless id
24
24
 
25
25
  response = client
26
- .post("/#{resource_name.pluralize}/#{id}/actions/#{name}", params)
26
+ .post("#{resource_path}/#{id}/actions/#{name}", params)
27
27
 
28
28
  if response.key?(:actions)
29
29
  response[:actions].map { |r| Action.new r }
@@ -5,16 +5,31 @@ module HCloud
5
5
  module Creatable
6
6
  extend ActiveSupport::Concern
7
7
 
8
- included do
8
+ included do # rubocop:disable Metrics/BlockLength
9
9
  attribute :created, :datetime
10
10
 
11
11
  def create
12
- assign_attributes client
13
- .post("/#{resource_name.pluralize}", creatable_params)
14
- .tap { |r| r[resource_name.to_sym].merge!(r.slice(:root_password)) }
15
- .fetch(resource_name.to_sym)
12
+ response = client
13
+ .post(resource_path, creatable_params)
16
14
 
17
- self
15
+ # Some resources return an action instead of the resource itself (e.g. Storage Box API)
16
+ if response.key?(:action)
17
+ # Set the ID from the action response
18
+ self.id = response
19
+ .dig(:action, :resources)
20
+ .find { |r| r[:type] == [resource_class&.resource_name, resource_name].compact.join("_") }
21
+ .fetch(:id)
22
+
23
+ # Return an Action instance
24
+ Action.new response[:action]
25
+ else
26
+ # Set the attributes from the response
27
+ assign_attributes response[resource_name.to_sym]
28
+ .merge!(response.slice(:root_password))
29
+
30
+ # Return the resource instance
31
+ self
32
+ end
18
33
  end
19
34
 
20
35
  def created?
@@ -9,12 +9,17 @@ module HCloud
9
9
  def delete
10
10
  raise Errors::MissingIDError unless id
11
11
 
12
- client
13
- .delete("/#{resource_name.pluralize}/#{id}")
12
+ response = client
13
+ .delete("#{resource_path}/#{id}")
14
14
 
15
15
  @deleted = true
16
16
 
17
- self
17
+ # Return the resource instance
18
+ return self unless response.is_a?(Hash) && response.key?(:action)
19
+
20
+ # Some resources return an action instead of the resource itself (e.g. Storage Box API)
21
+ # Return an Action instance
22
+ Action.new response[:action]
18
23
  end
19
24
 
20
25
  def deleted?
@@ -10,7 +10,7 @@ module HCloud
10
10
  raise Errors::MissingIDError unless id
11
11
 
12
12
  Metrics.new client
13
- .get("/#{resource_name.pluralize}/#{id}/metrics", type: Array(type).join(","), start: from.iso8601, end: to.iso8601, step: step)
13
+ .get("#{resource_path}/#{id}/metrics", type: Array(type).join(","), start: from.iso8601, end: to.iso8601, step: step)
14
14
  .fetch(:metrics)
15
15
  end
16
16
  end
@@ -10,7 +10,7 @@ module HCloud
10
10
  raise Errors::MissingIDError unless id
11
11
 
12
12
  assign_attributes client
13
- .get("/#{resource_name.pluralize}/#{id}")
13
+ .get("#{resource_path}/#{id}")
14
14
  .fetch(resource_name.to_sym)
15
15
 
16
16
  self
@@ -24,14 +24,14 @@ module HCloud
24
24
  raise Errors::MissingIDError unless id
25
25
 
26
26
  new client
27
- .get("/#{resource_name.pluralize}/#{id}")
27
+ .get("#{resource_path}/#{id}")
28
28
  .fetch(resource_name.to_sym)
29
29
  end
30
30
 
31
31
  def all
32
32
  Collection.new do |params|
33
33
  response = client
34
- .get("/#{resource_name.pluralize}", params)
34
+ .get(resource_path, params)
35
35
 
36
36
  data = response
37
37
  .fetch(resource_name.pluralize.to_sym)
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ # @!visibility private
5
+ module Subresource
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ # For super resources
10
+ class_attribute :subresource_names
11
+
12
+ self.subresource_names = []
13
+
14
+ # For subresources
15
+ class_attribute :resource_class
16
+ end
17
+
18
+ class_methods do
19
+ def inherited(subclass)
20
+ super
21
+
22
+ subclass.subresource_names = subresource_names.dup
23
+ end
24
+
25
+ # For super resources
26
+ def subresource(name, type = name)
27
+ subresource_names << name.to_s.pluralize
28
+
29
+ define_method(name.to_s.pluralize) do
30
+ raise Errors::MissingIDError unless id
31
+
32
+ SubCollection.new(name, type, self)
33
+ end
34
+ end
35
+
36
+ # For subresources
37
+ def subresource_of(name, type = name)
38
+ self.resource_class = ActiveModel::Type
39
+ .lookup(type)
40
+ .resource_class
41
+
42
+ attribute name, :integer
43
+
44
+ # TODO: override that returns the resource class instance instead of the ID?
45
+ end
46
+
47
+ def resource_path
48
+ "/#{resource_name.pluralize}"
49
+ end
50
+ end
51
+
52
+ def resource_path
53
+ if resource_class && (id = send(resource_class.resource_name)).present?
54
+ # Nested resources (e.g. /storage_boxes/123/subaccounts)
55
+ "/#{resource_class.resource_name.pluralize}/#{id}/#{resource_name.pluralize}"
56
+ else
57
+ # Top-level resources (e.g. /servers)
58
+ "/#{resource_name.pluralize}"
59
+ end
60
+ end
61
+ end
62
+ end
@@ -12,7 +12,7 @@ module HCloud
12
12
  assign_attributes attributes
13
13
 
14
14
  assign_attributes client
15
- .put("/#{resource_name.pluralize}/#{id}", updatable_params)
15
+ .put("#{resource_path}/#{id}", updatable_params)
16
16
  .fetch(resource_name.to_sym)
17
17
 
18
18
  self
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class StorageBoxAccessSettings < Entity
5
+ attribute :reachable_externally, :boolean
6
+ attribute :samba_enabled, :boolean
7
+ attribute :ssh_enabled, :boolean
8
+ attribute :webdav_enabled, :boolean
9
+ attribute :zfs_enabled, :boolean
10
+
11
+ alias reachable_externally? reachable_externally
12
+ alias samba_enabled? samba_enabled
13
+ alias ssh_enabled? ssh_enabled
14
+ alias webdav_enabled? webdav_enabled
15
+ alias zfs_enabled? zfs_enabled
16
+ end
17
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class StorageBoxPrice < Entity
5
+ attribute :location
6
+ attribute :price_hourly, :amount
7
+ attribute :price_monthly, :amount
8
+ attribute :setup_fee, :amount
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class StorageBoxSnapshotPlan < Entity
5
+ attribute :max_snapshots, :integer
6
+ attribute :minute, :integer
7
+ attribute :hour, :integer
8
+ attribute :day_of_week, :integer
9
+ attribute :day_of_month, :integer
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class StorageBoxSnapshotStats < Entity
5
+ attribute :size, :integer
6
+ attribute :size_filesystem, :integer
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class StorageBoxStats < Entity
5
+ attribute :size, :integer
6
+ attribute :size_data, :integer
7
+ attribute :size_snapshots, :integer
8
+ end
9
+ end