hetznercloud 1.0.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/README.md +32 -8
  4. data/config/inflections.rb +12 -3
  5. data/lib/core_ext/send_wrap.rb +11 -4
  6. data/lib/hcloud/concerns/actionable.rb +9 -2
  7. data/lib/hcloud/concerns/concerns.rb +8 -0
  8. data/lib/hcloud/concerns/creatable.rb +3 -2
  9. data/lib/hcloud/concerns/deletable.rb +2 -0
  10. data/lib/hcloud/concerns/meterable.rb +17 -0
  11. data/lib/hcloud/concerns/queryable.rb +4 -0
  12. data/lib/hcloud/concerns/singleton.rb +25 -0
  13. data/lib/hcloud/concerns/updatable.rb +2 -0
  14. data/lib/hcloud/entities/algorithm.rb +7 -0
  15. data/lib/hcloud/entities/certificate_status.rb +9 -0
  16. data/lib/hcloud/entities/floating_ip_price.rb +7 -0
  17. data/lib/hcloud/entities/floating_ip_prices.rb +8 -0
  18. data/lib/hcloud/entities/health_check.rb +12 -0
  19. data/lib/hcloud/entities/health_check_http.rb +13 -0
  20. data/lib/hcloud/entities/health_status.rb +8 -0
  21. data/lib/hcloud/entities/image_price.rb +7 -0
  22. data/lib/hcloud/entities/ipv4.rb +12 -0
  23. data/lib/hcloud/entities/ipv6.rb +12 -0
  24. data/lib/hcloud/entities/label_selector.rb +7 -0
  25. data/lib/hcloud/entities/load_balancer_private_net.rb +8 -0
  26. data/lib/hcloud/entities/load_balancer_public_net.rb +11 -0
  27. data/lib/hcloud/entities/load_balancer_type_price.rb +9 -0
  28. data/lib/hcloud/entities/private_net.rb +10 -0
  29. data/lib/hcloud/entities/public_net.rb +10 -0
  30. data/lib/hcloud/entities/route.rb +8 -0
  31. data/lib/hcloud/entities/server_backup_price.rb +7 -0
  32. data/lib/hcloud/entities/server_type_price.rb +9 -0
  33. data/lib/hcloud/entities/service.rb +16 -0
  34. data/lib/hcloud/entities/service_http.rb +16 -0
  35. data/lib/hcloud/entities/subnet.rb +11 -0
  36. data/lib/hcloud/entities/target.rb +15 -0
  37. data/lib/hcloud/entities/target_ip.rb +7 -0
  38. data/lib/hcloud/entities/target_target.rb +15 -0
  39. data/lib/hcloud/entities/targets.rb +13 -0
  40. data/lib/hcloud/entities/traffic_price.rb +7 -0
  41. data/lib/hcloud/entities/used_by.rb +8 -0
  42. data/lib/hcloud/entities/volume_price.rb +7 -0
  43. data/lib/hcloud/entity.rb +1 -0
  44. data/lib/hcloud/errors.rb +32 -2
  45. data/lib/hcloud/http.rb +12 -4
  46. data/lib/hcloud/resource_type.rb +41 -2
  47. data/lib/hcloud/resources/certificate.rb +131 -0
  48. data/lib/hcloud/resources/firewall.rb +57 -3
  49. data/lib/hcloud/resources/floating_ip.rb +2 -3
  50. data/lib/hcloud/resources/image.rb +1 -1
  51. data/lib/hcloud/resources/load_balancer.rb +107 -0
  52. data/lib/hcloud/resources/load_balancer_type.rb +38 -0
  53. data/lib/hcloud/resources/network.rb +142 -0
  54. data/lib/hcloud/resources/pricing.rb +34 -0
  55. data/lib/hcloud/resources/server.rb +12 -15
  56. data/lib/hcloud/resources/volume.rb +4 -5
  57. data/lib/hcloud/version.rb +2 -2
  58. data/lib/hcloud.rb +0 -2
  59. metadata +38 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 75623886cacdbf6d5513f45eb32c0d34ef0c8f0c1adee2bc7e69bf049b9c77ce
4
- data.tar.gz: 8055fc431b7a33ef53c6f30ca9002e36f91e1c723197294bf1cc8c00d8035072
3
+ metadata.gz: 78ef10de0c462ae7e1c5bf47c747d25a110551f817800b70b2aef7f5a045db5c
4
+ data.tar.gz: d9833600b525f01a5879888809a401df07bb7120f2d42db2e43220e0897cbfb5
5
5
  SHA512:
6
- metadata.gz: ccc0bcd9ea354b43cd7b235b788f516a2665066580f44cd25e9d17d6e206680e3cc33786c14c1e47a5948c606588ef517e0a371a6de8537365e8697fea04a16d
7
- data.tar.gz: cce03b3d75507f236152b04b731bd85cf88e15bef217805f6758e1fbf7dc12eb66e36b24717ee01680b16226f20d457b301436ca83d03aa183b6f7945f93dda0
6
+ metadata.gz: 20a46b53f9caa94a730c512208817c3ec7eb871983ade5bdd8acf2c19f77089084a31648c7b10d4d25d7cf3004f440d6732729398836e437838315fb01ec1985
7
+ data.tar.gz: 6cd6709f99a23259d4e82a93285aa415358cdc51dff6489911df5c35a06c6d85005c65eee5a42021bd69a665f33b620196d3657675122bd1c78da0d2d374c869
data/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## HCloud v1.3.1
4
+
5
+ - Add missing Server#user_data
6
+
7
+ ## HCloud v1.3.0
8
+
9
+ - Implemented Load Balancers
10
+ - Implemented Load Balancer Types
11
+
12
+ ## HCloud v1.2.0
13
+
14
+ - Implemented Networks
15
+ - Implemented Network Actions
16
+ - Implemented Pricing
17
+ - Implemented Certificates
18
+ - Implemented Certificate Actions
19
+
20
+ ## HCloud v1.1.0
21
+
22
+ - Implemented Firewall Actions
23
+
3
24
  ## HCloud v1.0.0
4
25
 
5
26
  Initial release
data/README.md CHANGED
@@ -74,24 +74,24 @@ Not all Hetzner Cloud API endpoints have been implemented yet.
74
74
  | Resource | State |
75
75
  |-----------------------|-----------------------|
76
76
  | Actions | Implemented |
77
- | Certificates | Not implemented |
78
- | Certificate Actions | Not implemented |
77
+ | Certificates | Implemented |
78
+ | Certificate Actions | Implemented |
79
79
  | Datacenters | Implemented |
80
80
  | Firewalls | Implemented |
81
- | Firewall Actions | Not implemented |
81
+ | Firewall Actions | Implemented |
82
82
  | Floating IPs | Implemented |
83
83
  | Floating IP Actions | Implemented |
84
84
  | Images | Implemented |
85
85
  | Image Actions | Implemented |
86
86
  | ISOs | Implemented |
87
- | Load Balancers | Not implemented |
87
+ | Load Balancers | Implemented |
88
88
  | Load Balancer Actions | Not implemented |
89
- | Load Balancer Types | Not implemented |
89
+ | Load Balancer Types | Implemented |
90
90
  | Locations | Implemented |
91
- | Networks | Not implemented |
92
- | Network Actions | Not implemented |
91
+ | Networks | Implemented |
92
+ | Network Actions | Implemented |
93
93
  | Placement Groups | Implemented |
94
- | Pricing | Not implemented |
94
+ | Pricing | Implemented |
95
95
  | Servers | Partially implemented |
96
96
  | Server Actions | Not implemented |
97
97
  | Server Types | Implemented |
@@ -109,6 +109,30 @@ bundle exec rspec
109
109
  bundle exec rspec --tag integration
110
110
  ```
111
111
 
112
+ ## Debugging
113
+
114
+ ### Logging
115
+
116
+ When using the gem in your code, you can pass a `logger:` argument to `HCloud::Client`:
117
+
118
+ ```ruby
119
+ logger = Logger.new("log/http.log")
120
+ logger.level = :debug
121
+
122
+ client = HCloud::Client.new(access_token: "my_access_token", logger: logger)
123
+ ```
124
+
125
+ When executing the test suite, set `LOG_LEVEL` environment variable to `debug` in order to see HTTP requests.
126
+
127
+ ### Endpoint
128
+
129
+ `HCloud::Client` also accepts an alternate endpoint:
130
+
131
+
132
+ ```ruby
133
+ client = HCloud::Client.new(access_token: "my_access_token", endpoint: "https://myproxy/v1")
134
+ ```
135
+
112
136
  ## Releasing
113
137
 
114
138
  To release a new version, update the version number in `lib/hcloud/version.rb`, update the changelog, commit the files and create a git tag starting with `v`, and push it to the repository.
@@ -2,18 +2,27 @@
2
2
 
3
3
  HCloud.loader.inflector.inflect(
4
4
  "dns_pointer" => "DNSPointer",
5
- "hcloud" => "HCloud",
6
- "ssh_key" => "SSHKey",
7
5
  "floating_ip" => "FloatingIP",
6
+ "floating_ip_price" => "FloatingIPPrice",
7
+ "floating_ip_prices" => "FloatingIPPrices",
8
+ "floating_ips" => "FloatingIPs",
9
+ "hcloud" => "HCloud",
10
+ "health_check_http" => "HealthCheckHTTP",
8
11
  "http" => "HTTP",
9
12
  "ip_not_available" => "IPNotAvailable",
13
+ "ipv4" => "IPv4",
14
+ "ipv6" => "IPv6",
10
15
  "iso" => "ISO",
11
16
  "iso_type" => "ISOType",
17
+ "service_http" => "ServiceHTTP",
18
+ "ssh_key" => "SSHKey",
19
+ "target_ip" => "TargetIP",
12
20
  )
13
21
 
14
22
  ActiveSupport::Inflector.inflections(:en) do |inflect|
15
23
  inflect.acronym "DNS"
16
- inflect.acronym "JSON"
24
+ inflect.acronym "HTTP"
17
25
  inflect.acronym "IP"
18
26
  inflect.acronym "ISO"
27
+ inflect.acronym "JSON"
19
28
  end
@@ -2,12 +2,19 @@
2
2
 
3
3
  module CoreExt
4
4
  module SendWrap
5
- # Send a message to self, or all objects contained in self (for enumerables)
5
+ # Send a message to self, or all objects contained in self (for arrays)
6
6
 
7
- # FIXME: { env: "prod" }.send_wrap(:try, :to_h) returns { env: nil }
7
+ # NOTE: { env: "prod" }.send_wrap(:try, :to_h) returns { env: nil }
8
+ # NOTE: ["example.com"].send_wrap(:try, to_h) return [nil]
9
+ # Use a block for the above cases:
10
+ # { env: "prod" }.send_wrap { |o| o.try(:to_h) || o }
8
11
 
9
- def send_wrap(method_name, ...)
10
- is_a?(Array) ? map { |v| v.send(method_name, ...) } : send(method_name, ...)
12
+ def send_wrap(...)
13
+ if is_a?(Array)
14
+ map { |v| block_given? ? yield(v) : v.send(...) }
15
+ else
16
+ block_given? ? yield(self) : send(...)
17
+ end
11
18
  end
12
19
  end
13
20
  end
@@ -19,9 +19,16 @@ module HCloud
19
19
  action_names << name.to_s
20
20
 
21
21
  define_method(name) do |**params|
22
- Action.new client
22
+ raise Errors::MissingIDError unless id
23
+
24
+ response = client
23
25
  .post("/#{resource_name.pluralize}/#{id}/actions/#{name}", params)
24
- .fetch(:action)
26
+
27
+ if response.key?(:actions)
28
+ response[:actions].map { |r| Action.new r }
29
+ else
30
+ Action.new response[:action]
31
+ end
25
32
  end
26
33
  end
27
34
  end
@@ -24,6 +24,14 @@ module HCloud
24
24
  def deletable
25
25
  include Deletable
26
26
  end
27
+
28
+ def meterable
29
+ include Meterable
30
+ end
31
+
32
+ def singleton
33
+ include Singleton
34
+ end
27
35
  end
28
36
  end
29
37
  end
@@ -10,6 +10,7 @@ module HCloud
10
10
  def create
11
11
  assign_attributes client
12
12
  .post("/#{resource_name.pluralize}", creatable_params)
13
+ .tap { |r| r[resource_name.to_sym].merge!(r.slice(:root_password)) }
13
14
  .fetch(resource_name.to_sym)
14
15
  end
15
16
 
@@ -29,9 +30,9 @@ module HCloud
29
30
 
30
31
  attributes
31
32
  .slice(*simple_attributes.map(&:to_s))
32
- .transform_values { |v| v&.send_wrap(:try, :to_h) || v&.send_wrap(:to_s) }
33
+ .transform_values { |v| v&.send_wrap { |o| o.try(:to_h) || o } || v&.send_wrap(:to_s) }
33
34
  .merge(nested_attributes.reduce(&:merge)&.map { |k, v| [k.to_s, Array(v).filter_map { |w| send(k)&.send_wrap(w) }.first] }.to_h)
34
- .compact
35
+ .compact_blank
35
36
  end
36
37
  # rubocop:enable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
37
38
  end
@@ -6,6 +6,8 @@ module HCloud
6
6
 
7
7
  included do
8
8
  def delete
9
+ raise Errors::MissingIDError unless id
10
+
9
11
  client
10
12
  .delete("/#{resource_name.pluralize}/#{id}")
11
13
 
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ module Meterable
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ def metrics(type:, from:, to:, step: nil)
9
+ raise Errors::MissingIDError unless id
10
+
11
+ Metrics.new client
12
+ .get("/#{resource_name.pluralize}/#{id}/metrics", type: Array(type).join(","), start: from.iso8601, end: to.iso8601, step: step)
13
+ .fetch(:metrics)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -6,6 +6,8 @@ module HCloud
6
6
 
7
7
  included do
8
8
  def reload
9
+ raise Errors::MissingIDError unless id
10
+
9
11
  assign_attributes client
10
12
  .get("/#{resource_name.pluralize}/#{id}")
11
13
  .fetch(resource_name.to_sym)
@@ -16,6 +18,8 @@ module HCloud
16
18
 
17
19
  class_methods do
18
20
  def find(id)
21
+ raise Errors::MissingIDError unless id
22
+
19
23
  new client
20
24
  .get("/#{resource_name.pluralize}/#{id}")
21
25
  .fetch(resource_name.to_sym)
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ module Singleton
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ def reload
9
+ assign_attributes client
10
+ .get("/#{resource_name}")
11
+ .fetch(resource_name.to_sym)
12
+
13
+ self
14
+ end
15
+ end
16
+
17
+ class_methods do
18
+ def find
19
+ new client
20
+ .get("/#{resource_name}")
21
+ .fetch(resource_name.to_sym)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -6,6 +6,8 @@ module HCloud
6
6
 
7
7
  included do
8
8
  def update
9
+ raise Errors::MissingIDError unless id
10
+
9
11
  assign_attributes client
10
12
  .put("/#{resource_name.pluralize}/#{id}", updatable_params)
11
13
  .fetch(resource_name.to_sym)
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class Algorithm < Entity
5
+ attribute :type
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class CertificateStatus < Entity
5
+ attribute :error, :error
6
+ attribute :issuance
7
+ attribute :renewal
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class FloatingIPPrice < Entity
5
+ attribute :price_monthly, :amount
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class FloatingIPPrices < Entity
5
+ attribute :type
6
+ attribute :prices, :price
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class HealthCheck < Entity
5
+ attribute :http, :health_check_http
6
+ attribute :interval, :integer
7
+ attribute :port, :integer
8
+ attribute :protocol
9
+ attribute :retries, :integer
10
+ attribute :timeout, :integer
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class HealthCheckHTTP < Entity
5
+ attribute :domain
6
+ attribute :path
7
+ attribute :response
8
+ attribute :status_code, array: true, default: -> { [] }
9
+ attribute :tls
10
+
11
+ alias tls? tls
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class HealthStatus < Entity
5
+ attribute :listen_port, :integer
6
+ attribute :status
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class ImagePrice < Entity
5
+ attribute :price_per_gb_month, :amount
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class IPv4 < Entity
5
+ attribute :blocked, :boolean
6
+ attribute :dns_ptr
7
+ attribute :id, :integer
8
+ attribute :ip
9
+
10
+ alias blocked? blocked
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class IPv6 < Entity
5
+ attribute :blocked, :boolean
6
+ attribute :dns_ptr, :dns_pointer, array: true, default: -> { [] }
7
+ attribute :id, :integer
8
+ attribute :ip
9
+
10
+ alias blocked? blocked
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class LabelSelector < Entity
5
+ attribute :selector
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class LoadBalancerPrivateNet < Entity
5
+ attribute :ip
6
+ attribute :network
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class LoadBalancerPublicNet < Entity
5
+ attribute :enabled, :boolean
6
+ attribute :ipv4, :dns_pointer
7
+ attribute :ipv6, :dns_pointer
8
+
9
+ alias enabled? enabled
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class LoadBalancerTypePrice < Entity
5
+ attribute :id, :integer
6
+ attribute :name
7
+ attribute :prices, :price, array: true, default: -> { [] }
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class PrivateNet < Entity
5
+ attribute :alias_ips, array: true, default: -> { [] }
6
+ attribute :ip
7
+ attribute :mac_address
8
+ attribute :network, :network
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class PublicNet < Entity
5
+ attribute :firewalls, :firewall, array: true, default: -> { [] }
6
+ attribute :floating_ips, :floating_ip, array: true, default: -> { [] }
7
+ attribute :ipv4, :ipv4
8
+ attribute :ipv6, :ipv6
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class Route < Entity
5
+ attribute :destination
6
+ attribute :gateway
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class ServerBackupPrice < Entity
5
+ attribute :percentage
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class ServerTypePrice < Entity
5
+ attribute :id, :integer
6
+ attribute :name
7
+ attribute :prices, :price, array: true, default: -> { [] }
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class Service < Entity
5
+ attribute :listen_port, :integer
6
+ attribute :destination_port, :integer
7
+
8
+ attribute :protocol
9
+ attribute :proxyprotocol, :boolean
10
+
11
+ attribute :health_check, :health_check
12
+ attribute :http, :service_http
13
+
14
+ alias proxyprotocol? proxyprotocol
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class ServiceHTTP < Entity
5
+ attribute :certificates, :certificate, array: true, default: -> { [] }
6
+
7
+ attribute :cookie_lifetime, :integer
8
+ attribute :cookie_name
9
+
10
+ attribute :redirect_http, :boolean
11
+ attribute :sticky_sessions, :boolean
12
+
13
+ alias redirect_http? redirect_http
14
+ alias sticky_sessions? sticky_sessions
15
+ end
16
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class Subnet < Entity
5
+ attribute :type
6
+ attribute :network_zone
7
+ attribute :gateway
8
+ attribute :ip_range
9
+ attribute :vswitch_id
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class Target < Entity
5
+ attribute :type
6
+
7
+ attribute :health_status, :health_status, array: true, default: -> { [] }
8
+
9
+ attribute :server, :server
10
+
11
+ attribute :use_private_ip, :boolean
12
+
13
+ alias use_private_ip? use_private_ip
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class TargetIP < Entity
5
+ attribute :ip
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class TargetTarget < Entity
5
+ attribute :type
6
+
7
+ attribute :health_status, :health_status, array: true, default: -> { [] }
8
+
9
+ attribute :server, :server
10
+
11
+ attribute :use_private_ip, :boolean
12
+
13
+ alias use_private_ip? use_private_ip
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class Targets < Target
5
+ attribute :type
6
+
7
+ attribute :ip, :target_ip
8
+
9
+ attribute :label_selector, :label_selector
10
+
11
+ attribute :targets, :target, array: true, default: -> { [] }
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class TrafficPrice < Entity
5
+ attribute :price_per_tb, :amount
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class UsedBy < Entity
5
+ attribute :id, :integer
6
+ attribute :type
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class VolumePrice < Entity
5
+ attribute :price_per_gb_month, :amount
6
+ end
7
+ end
data/lib/hcloud/entity.rb CHANGED
@@ -18,6 +18,7 @@ module HCloud
18
18
  def to_h
19
19
  attributes
20
20
  .transform_values { |v| v.try(:to_h) || v }
21
+ .compact_blank
21
22
  end
22
23
  end
23
24
  end