hetznercloud 1.4.0 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/Gemfile +13 -0
  4. data/README.md +76 -32
  5. data/config/inflections.rb +3 -0
  6. data/lib/hcloud/client.rb +4 -3
  7. data/lib/hcloud/collection.rb +4 -2
  8. data/lib/hcloud/concerns/concerns.rb +4 -0
  9. data/lib/hcloud/concerns/labelable.rb +11 -0
  10. data/lib/hcloud/concerns/queryable.rb +2 -0
  11. data/lib/hcloud/entities/primary_ip_prices.rb +8 -0
  12. data/lib/hcloud/entities/private_network.rb +15 -0
  13. data/lib/hcloud/entities/protection.rb +0 -2
  14. data/lib/hcloud/entities/server_protection.rb +11 -0
  15. data/lib/hcloud/errors.rb +1 -0
  16. data/lib/hcloud/http.rb +4 -2
  17. data/lib/hcloud/resource_type.rb +32 -2
  18. data/lib/hcloud/resources/action.rb +5 -6
  19. data/lib/hcloud/resources/certificate.rb +8 -6
  20. data/lib/hcloud/resources/datacenter.rb +1 -1
  21. data/lib/hcloud/resources/firewall.rb +7 -5
  22. data/lib/hcloud/resources/floating_ip.rb +7 -5
  23. data/lib/hcloud/resources/image.rb +6 -7
  24. data/lib/hcloud/resources/iso.rb +1 -1
  25. data/lib/hcloud/resources/load_balancer.rb +7 -5
  26. data/lib/hcloud/resources/load_balancer_type.rb +1 -1
  27. data/lib/hcloud/resources/location.rb +1 -1
  28. data/lib/hcloud/resources/metadata.rb +33 -0
  29. data/lib/hcloud/resources/network.rb +5 -3
  30. data/lib/hcloud/resources/placement_group.rb +7 -5
  31. data/lib/hcloud/resources/pricing.rb +2 -0
  32. data/lib/hcloud/resources/primary_ip.rb +8 -6
  33. data/lib/hcloud/resources/server.rb +9 -7
  34. data/lib/hcloud/resources/server_type.rb +2 -1
  35. data/lib/hcloud/resources/ssh_key.rb +8 -6
  36. data/lib/hcloud/resources/volume.rb +8 -6
  37. data/lib/hcloud/version.rb +2 -2
  38. data/lib/http/mime_type/yaml.rb +23 -0
  39. data/lib/http/rate_limiter.rb +40 -0
  40. metadata +9 -128
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a1b9b0de15d2fe2aecdbfa6b00b46df9ec658855ebdafcabebe72f371dd98d50
4
- data.tar.gz: 6c39c3ee93d35767d355e522408d1285ce3777fc841753968ae9c33d0916cc6c
3
+ metadata.gz: 3e5950847db8b1e523a027c3197efebbef0dbcf3cdece53d46817e8d22ebf90c
4
+ data.tar.gz: 0a142f83f2ea3ffbc104501082ac72a26986d46ace0964c70a147be945bf73fd
5
5
  SHA512:
6
- metadata.gz: 7a9971d0195c839594b88759d828dc04f98e36d37eab7880d27f4299f8266d2e37676eea3b60399440bed9240e6d39190dba0af75f2d32bfe78c5e42bb160cd5
7
- data.tar.gz: bbecc7998329638d8499d0a33c877cdc5857b2a94c80633672a874f6828cc69f29e67d8e3a618b21db5cd84d87cf66cecd2e2ee3ddcfa16db00f841394f0ea85
6
+ metadata.gz: a4de38d5d298b9b55611fac064b6bd5f6f0acff82e0286cae05195546a7d8e5b9d99bacdb58a7a03affec4bc22979baf59dfc7a54aca8107936ad22422ce0ab9
7
+ data.tar.gz: 1ff509622967a9c449e5db033090e3a599160fd7c3859acc32544793c2a6e0365821be729673ff75f85074188a3ce69abc11d37bafaec8254a134453d7c7e5e3
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## HCloud v1.5.1 (2023-04-20)
4
+
5
+ - Add `Unavailable` error class
6
+ - Add `architecture` attribute to `ServerType`
7
+
8
+ ## HCloud v1.5.0 (2023-02-01)
9
+
10
+ - Add pricing for Primary IPs
11
+ - Add server Metadata resource
12
+ - Add support for rate limits
13
+ - `Action#resources` now returns a list of resources instead of a list of hashes
14
+ - Separate server protection entity from other protection entity (only server protection includes `rebuild`)
15
+ - Add shorthand methods for `.first`, `.last`, `.count`, `.where`, `.sort`, `.each`, and `.empty?` on resource
16
+ - Add `label_selector:` argument to `HCloud::Collection`
17
+
3
18
  ## HCloud v1.4.0 (2023-01-22)
4
19
 
5
20
  - Implemented Primary IPs
data/Gemfile CHANGED
@@ -4,3 +4,16 @@ source "https://rubygems.org"
4
4
 
5
5
  # Specify your gem's dependencies in hcloud.gemspec
6
6
  gemspec
7
+
8
+ group :development, :test do
9
+ gem "byebug", require: false
10
+ gem "dotenv", require: false
11
+ gem "ffaker", require: false
12
+ gem "rake", require: false
13
+ gem "rspec", require: false
14
+ gem "rubocop", require: false
15
+ gem "rubocop-performance", require: false
16
+ gem "rubocop-rspec", require: false
17
+ gem "timecop", require: false
18
+ gem "webmock", require: false
19
+ end
data/README.md CHANGED
@@ -69,37 +69,82 @@ It expects you to use it in a sane way.
69
69
 
70
70
  ## Features
71
71
 
72
- Not all Hetzner Cloud API endpoints have been implemented yet.
73
-
74
- | Resource | State |
75
- |-----------------------|-----------------------|
76
- | Actions | Implemented |
77
- | Certificates | Implemented |
78
- | Certificate Actions | Implemented |
79
- | Datacenters | Implemented |
80
- | Firewalls | Implemented |
81
- | Firewall Actions | Implemented |
82
- | Floating IPs | Implemented |
83
- | Floating IP Actions | Implemented |
84
- | Images | Implemented |
85
- | Image Actions | Implemented |
86
- | ISOs | Implemented |
87
- | Load Balancers | Implemented |
88
- | Load Balancer Actions | Not implemented |
89
- | Load Balancer Types | Implemented |
90
- | Locations | Implemented |
91
- | Primary IPs | Implemented |
92
- | Primary IP Actions | Implemented |
93
- | Networks | Implemented |
94
- | Network Actions | Implemented |
95
- | Placement Groups | Implemented |
96
- | Pricing | Implemented |
97
- | Servers | Partially implemented |
98
- | Server Actions | Not implemented |
99
- | Server Types | Implemented |
100
- | SSH Keys | Implemented |
101
- | Volumes | Implemented |
102
- | Volume Actions | Implemented |
72
+ The following table lists the Hetzner Cloud API endpoints that are currently implemented.
73
+
74
+ | Resource | State |
75
+ |----------------------------------------------------------------|-----------------------|
76
+ | [Actions](lib/hcloud/resources/action.rb) | Implemented |
77
+ | [Certificates](lib/hcloud/resources/certificate.rb) | Implemented |
78
+ | [Certificate Actions](lib/hcloud/resources/certificate.rb) | Implemented |
79
+ | [Datacenters](lib/hcloud/resources/datacenter.rb) | Implemented |
80
+ | [Firewalls](lib/hcloud/resources/firewall.rb) | Implemented |
81
+ | [Firewall Actions](lib/hcloud/resources/firewall.rb) | Implemented |
82
+ | [Floating IPs](lib/hcloud/resources/floating_ip.rb) | Implemented |
83
+ | [Floating IP Actions](lib/hcloud/resources/floating_ip.rb) | Implemented |
84
+ | [Images](lib/hcloud/resources/image.rb) | Implemented |
85
+ | [Image Actions](lib/hcloud/resources/image.rb) | Implemented |
86
+ | [ISOs](lib/hcloud/resources/iso.rb) | Implemented |
87
+ | [Load Balancers](lib/hcloud/resources/load_balancer.rb) | Implemented |
88
+ | [Load Balancer Actions](lib/hcloud/resources/load_balancer.rb) | Not implemented |
89
+ | [Load Balancer Types](lib/hcloud/resources/load_balancer.rb) | Implemented |
90
+ | [Locations](lib/hcloud/resources/location.rb) | Implemented |
91
+ | [Primary IPs](lib/hcloud/resources/primary_ip.rb) | Implemented |
92
+ | [Primary IP Actions](lib/hcloud/resources/primary_ip.rb) | Implemented |
93
+ | [Networks](lib/hcloud/resources/network.rb) | Implemented |
94
+ | [Network Actions](lib/hcloud/resources/network.rb) | Implemented |
95
+ | [Placement Groups](lib/hcloud/resources/placement_group.rb) | Implemented |
96
+ | [Pricing](lib/hcloud/resources/pricing.rb) | Implemented |
97
+ | [Servers](lib/hcloud/resources/server.rb) | Partially implemented |
98
+ | [Server Actions](lib/hcloud/resources/server.rb) | Not implemented |
99
+ | [Server Types](lib/hcloud/resources/server_type.rb) | Implemented |
100
+ | [SSH Keys](lib/hcloud/resources/ssh_key.rb) | Implemented |
101
+ | [Volumes](lib/hcloud/resources/volume.rb) | Implemented |
102
+ | [Volume Actions](lib/hcloud/resources/volume.rb) | Implemented |
103
+ | | |
104
+ | [Metadata](lib/hcloud/resources/metadata.rb) | Implemented |
105
+
106
+ ### Pagination
107
+
108
+ Paginated resources are wrapped in a `HCloud::Collection` that automatically fetches the next page when needed.
109
+ The collection acts as a (lazy) enumerator.
110
+ Call `to_a` to fetch all pages and parse all resources.
111
+
112
+ ### Rate limiting
113
+
114
+ From the [documentation](https://docs.hetzner.cloud/#rate-limiting):
115
+
116
+ > The default limit is 3600 requests per hour and per Project.
117
+ > The number of remaining requests increases gradually.
118
+ > For example, when your limit is 3600 requests per hour, the number of remaining requests will increase by 1 every second.
119
+
120
+ The client is able to handle the rate limiting by delaying the requests if necessary and executing them whenever possible.
121
+ To enable this behaviour, pass `rate_limit: true` as argument to `HCloud::Client.new`.
122
+ Client calls will block until possible to execute and then return.
123
+
124
+ ```ruby
125
+ client = HCloud::Client.new(access_token: "my_token", rate_limit: true)
126
+
127
+ # At least one request has to be made to enable the rate limiter
128
+ client.rate_limiter.limit # => nil
129
+ client.rate_limiter.remaining # => nil
130
+ client.rate_limiter.reset # => nil
131
+
132
+ HCloud::Server.create(...)
133
+
134
+ client.rate_limiter.limit # => 3600
135
+ client.rate_limiter.remaining # => 3599
136
+ client.rate_limiter.reset # => 2023-01-01 00:00:00 +0100
137
+
138
+ # Make a bunch of requests
139
+
140
+ client.rate_limiter.remaining # => 0
141
+
142
+ servers = HCloud::Server.all # Will block until remaining requests have regenerated (1 second by default) and then execute
143
+ ssh_keys = HCloud::SSHKey.all # Will block until remaining requests have regenerated (1 second by default) and then execute
144
+ ```
145
+
146
+ Since rate limits are per hour and per project, using multiple clients at the same time will interfere with the rate limiting mechanism.
147
+ To prevent this, wrap client calls in a loop that retries the call after it fails with a `HCloud::RateLimitExceeded` error.
103
148
 
104
149
  ## Testing
105
150
 
@@ -130,7 +175,6 @@ When executing the test suite, set `LOG_LEVEL` environment variable to `debug` i
130
175
 
131
176
  `HCloud::Client` also accepts an alternate endpoint:
132
177
 
133
-
134
178
  ```ruby
135
179
  client = HCloud::Client.new(access_token: "my_access_token", endpoint: "https://myproxy/v1")
136
180
  ```
@@ -15,9 +15,11 @@ HCloud.loader.inflector.inflect(
15
15
  "iso" => "ISO",
16
16
  "iso_type" => "ISOType",
17
17
  "primary_ip" => "PrimaryIP",
18
+ "primary_ip_prices" => "PrimaryIPPrices",
18
19
  "service_http" => "ServiceHTTP",
19
20
  "ssh_key" => "SSHKey",
20
21
  "target_ip" => "TargetIP",
22
+ "yaml" => "YAML",
21
23
  )
22
24
 
23
25
  ActiveSupport::Inflector.inflections(:en) do |inflect|
@@ -28,4 +30,5 @@ ActiveSupport::Inflector.inflections(:en) do |inflect|
28
30
  inflect.acronym "IPv6"
29
31
  inflect.acronym "ISO"
30
32
  inflect.acronym "JSON"
33
+ inflect.acronym "YAML"
31
34
  end
data/lib/hcloud/client.rb CHANGED
@@ -19,12 +19,13 @@ module HCloud
19
19
 
20
20
  self.connection = NilConnection.new
21
21
 
22
- attr_reader :access_token, :endpoint, :logger
22
+ attr_reader :access_token, :endpoint, :logger, :rate_limit
23
23
 
24
- def initialize(access_token:, endpoint: "https://api.hetzner.cloud/v1", logger: Logger.new("/dev/null"))
24
+ def initialize(access_token:, endpoint: "https://api.hetzner.cloud/v1", logger: Logger.new("/dev/null"), rate_limit: false)
25
25
  @access_token = access_token
26
26
  @endpoint = endpoint
27
27
  @logger = logger
28
+ @rate_limit = rate_limit
28
29
  end
29
30
 
30
31
  delegate :get, :put, :post, :delete, to: :http
@@ -32,7 +33,7 @@ module HCloud
32
33
  private
33
34
 
34
35
  def http
35
- @http ||= HTTP.new(access_token, endpoint, logger)
36
+ @http ||= HTTP.new(access_token, endpoint, logger, rate_limit)
36
37
  end
37
38
  end
38
39
  end
@@ -6,7 +6,7 @@ module HCloud
6
6
 
7
7
  attr_accessor :page, :previous_page, :next_page, :last_page, :per_page, :total_entries, :proc
8
8
 
9
- attr_reader :sort_by, :filter_by
9
+ attr_reader :sort_by, :filter_by, :label_selector
10
10
 
11
11
  def initialize(&block)
12
12
  @proc = block
@@ -24,8 +24,9 @@ module HCloud
24
24
  self
25
25
  end
26
26
 
27
- def where(**filter_by)
27
+ def where(label_selector: nil, **filter_by)
28
28
  @filter_by = filter_by
29
+ @label_selector = label_selector
29
30
 
30
31
  self
31
32
  end
@@ -70,6 +71,7 @@ module HCloud
70
71
  page: page,
71
72
  per_page: per_page,
72
73
  sort: sort_by,
74
+ label_selector: label_selector&.map { |k, v| "#{k}=#{v}" }&.join(","),
73
75
  **filter_by,
74
76
  }
75
77
  end
@@ -32,6 +32,10 @@ module HCloud
32
32
  def singleton
33
33
  include Singleton
34
34
  end
35
+
36
+ def labelable
37
+ include Labelable
38
+ end
35
39
  end
36
40
  end
37
41
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ module Labelable
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ attribute :labels, default: -> { {} }
9
+ end
10
+ end
11
+ end
@@ -17,6 +17,8 @@ module HCloud
17
17
  end
18
18
 
19
19
  class_methods do
20
+ delegate :first, :last, :count, :where, :sort, :each, :empty?, :any?, to: :all
21
+
20
22
  def find(id)
21
23
  raise Errors::MissingIDError unless id
22
24
 
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class PrimaryIPPrices < Entity
5
+ attribute :type
6
+ attribute :prices, :price
7
+ end
8
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class PrivateNetwork < Entity
5
+ attribute :ip
6
+ attribute :alias_ips, array: true, default: -> { [] }
7
+ attribute :interface_num, :integer
8
+ attribute :mac_address
9
+ attribute :network_id, :integer
10
+ attribute :network_name
11
+ attribute :network
12
+ attribute :subnet
13
+ attribute :gateway
14
+ end
15
+ end
@@ -3,9 +3,7 @@
3
3
  module HCloud
4
4
  class Protection < Entity
5
5
  attribute :delete, :boolean
6
- attribute :rebuild, :boolean
7
6
 
8
7
  alias delete? delete
9
- alias rebuild? rebuild
10
8
  end
11
9
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HCloud
4
+ class ServerProtection < Entity
5
+ attribute :delete, :boolean
6
+ attribute :rebuild, :boolean
7
+
8
+ alias delete? delete
9
+ alias rebuild? rebuild
10
+ end
11
+ end
data/lib/hcloud/errors.rb CHANGED
@@ -66,6 +66,7 @@ module HCloud
66
66
  class TargetAlreadyDefined < Error; end
67
67
  class TokenReadonly < Error; end
68
68
  class Unauthorized < Error; end
69
+ class Unavailable < Error; end
69
70
  class UniquenessError < Error; end
70
71
  class UnsupportedError < Error; end
71
72
 
data/lib/hcloud/http.rb CHANGED
@@ -4,12 +4,13 @@ require "http"
4
4
 
5
5
  module HCloud
6
6
  class HTTP
7
- attr_reader :access_token, :endpoint, :logger, :timeout
7
+ attr_reader :access_token, :endpoint, :logger, :rate_limit, :timeout
8
8
 
9
- def initialize(access_token, endpoint, logger, timeout = 10)
9
+ def initialize(access_token, endpoint, logger, rate_limit = false, timeout = 10)
10
10
  @access_token = access_token
11
11
  @endpoint = endpoint
12
12
  @logger = logger
13
+ @rate_limit = rate_limit
13
14
  @timeout = timeout
14
15
  end
15
16
 
@@ -80,6 +81,7 @@ module HCloud
80
81
  .headers(accept: "application/json", user_agent: "#{HCloud::NAME}/#{HCloud::VERSION}")
81
82
  .timeout(timeout)
82
83
  .use(logging: { logger: logger })
84
+ .then { |h| rate_limit ? h.use(:rate_limiter) : h }
83
85
  .encoding("utf-8")
84
86
  .auth("Bearer #{access_token}")
85
87
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # rubocop:disable Metrics/CyclomaticComplexity,Metrics/AbcSize
3
4
  module HCloud
4
5
  class ResourceType
5
6
  class_attribute :resource_class_name
@@ -10,7 +11,6 @@ module HCloud
10
11
  @array = array
11
12
  end
12
13
 
13
- # rubocop:disable Metrics/CyclomaticComplexity
14
14
  def cast(value)
15
15
  case value
16
16
  when nil, []
@@ -28,12 +28,13 @@ module HCloud
28
28
  when Hash # Attribute hash
29
29
  resource_class.new(value)
30
30
  when Array # List
31
+ raise ArgumentError, "cannot cast value: #{value} for type #{resource_class_name}" unless array?
32
+
31
33
  value.map { |v| cast(v) }
32
34
  else
33
35
  raise ArgumentError, "cannot cast value: #{value} for type #{resource_class_name}"
34
36
  end
35
37
  end
36
- # rubocop:enable Metrics/CyclomaticComplexity
37
38
 
38
39
  def resource_class
39
40
  @resource_class ||= resource_class_name.constantize
@@ -52,8 +53,32 @@ module HCloud
52
53
  .tap { |klass| HCloud.const_set(:"#{class_name.demodulize}ResourceType", klass) }
53
54
  end
54
55
  # rubocop:enable Naming/MethodName
56
+
57
+ class GenericType < ResourceType
58
+ def cast(value)
59
+ case value
60
+ when nil, []
61
+ array? ? [] : nil
62
+ when HCloud::Resource # Class
63
+ value
64
+ when Hash # Attribute hash
65
+ ActiveModel::Type
66
+ .lookup(value.fetch(:type).to_sym)
67
+ .cast(value.except(:type))
68
+ when Array # List
69
+ raise ArgumentError, "cannot cast value: #{value} for generic type" unless array?
70
+
71
+ value.map { |v| cast(v) }
72
+ else
73
+ raise ArgumentError, "cannot cast value: #{value} for generic type"
74
+ end
75
+ rescue KeyError => e
76
+ raise ArgumentError, "cannot cast value: #{value} for generic type: #{e.message}"
77
+ end
78
+ end
55
79
  end
56
80
  end
81
+ # rubocop:enable Metrics/CyclomaticComplexity,Metrics/AbcSize
57
82
 
58
83
  ActiveModel::Type.register(:action, HCloud::ResourceType.Type("HCloud::Action"))
59
84
  ActiveModel::Type.register(:algorithm, HCloud::ResourceType.Type("HCloud::Algorithm"))
@@ -86,18 +111,23 @@ ActiveModel::Type.register(:load_balancer_public_net, HCloud::ResourceType.Type(
86
111
  ActiveModel::Type.register(:load_balancer_type, HCloud::ResourceType.Type("HCloud::LoadBalancerType"))
87
112
  ActiveModel::Type.register(:load_balancer_type_price, HCloud::ResourceType.Type("HCloud::LoadBalancerTypePrice"))
88
113
  ActiveModel::Type.register(:location, HCloud::ResourceType.Type("HCloud::Location"))
114
+ ActiveModel::Type.register(:metadata, HCloud::ResourceType.Type("HCloud::Metadata"))
89
115
  ActiveModel::Type.register(:network, HCloud::ResourceType.Type("HCloud::Network"))
90
116
  ActiveModel::Type.register(:placement_group, HCloud::ResourceType.Type("HCloud::PlacementGroup"))
91
117
  ActiveModel::Type.register(:price, HCloud::ResourceType.Type("HCloud::Price"))
92
118
  ActiveModel::Type.register(:pricing, HCloud::ResourceType.Type("HCloud::Pricing"))
93
119
  ActiveModel::Type.register(:primary_ip, HCloud::ResourceType.Type("HCloud::PrimaryIP"))
120
+ ActiveModel::Type.register(:primary_ip_prices, HCloud::ResourceType.Type("HCloud::PrimaryIPPrices"))
94
121
  ActiveModel::Type.register(:private_net, HCloud::ResourceType.Type("HCloud::PrivateNet"))
122
+ ActiveModel::Type.register(:private_network, HCloud::ResourceType.Type("HCloud::PrivateNetwork"))
95
123
  ActiveModel::Type.register(:protection, HCloud::ResourceType.Type("HCloud::Protection"))
96
124
  ActiveModel::Type.register(:public_net, HCloud::ResourceType.Type("HCloud::PublicNet"))
125
+ ActiveModel::Type.register(:resource, HCloud::ResourceType::GenericType)
97
126
  ActiveModel::Type.register(:route, HCloud::ResourceType.Type("HCloud::Route"))
98
127
  ActiveModel::Type.register(:rule, HCloud::ResourceType.Type("HCloud::Rule"))
99
128
  ActiveModel::Type.register(:server, HCloud::ResourceType.Type("HCloud::Server"))
100
129
  ActiveModel::Type.register(:server_backup_price, HCloud::ResourceType.Type("HCloud::ServerBackupPrice"))
130
+ ActiveModel::Type.register(:server_protection, HCloud::ResourceType.Type("HCloud::ServerProtection"))
101
131
  ActiveModel::Type.register(:server_type, HCloud::ResourceType.Type("HCloud::ServerType"))
102
132
  ActiveModel::Type.register(:server_type_price, HCloud::ResourceType.Type("HCloud::ServerTypePrice"))
103
133
  ActiveModel::Type.register(:service, HCloud::ResourceType.Type("HCloud::Service"))
@@ -11,18 +11,18 @@ module HCloud
11
11
  #
12
12
  # == Sort actions
13
13
  #
14
- # HCloud::Action.all.sort(command: :desc)
14
+ # HCloud::Action.sort(command: :desc)
15
15
  # # => [#<HCloud::Action id: 1, ...>, ...]
16
16
  #
17
- # HCloud::Action.all.sort(:id, command: :asc)
17
+ # HCloud::Action.sort(:id, command: :asc)
18
18
  # # => [#<HCloud::Action id: 1, ...>, ...]
19
19
  #
20
20
  # == Search actions
21
21
  #
22
- # HCloud::Action.all.where(command: "my_action")
22
+ # HCloud::Action.where(command: "my_action")
23
23
  # # => #<HCloud::Action id: 1, ...>
24
24
  #
25
- # HCloud::Action.all.where(status: "success")
25
+ # HCloud::Action.where(status: "success")
26
26
  # # => #<HCloud::Action id: 1, ...>
27
27
  #
28
28
  # == Find action by ID
@@ -43,7 +43,6 @@ module HCloud
43
43
  attribute :status
44
44
  attribute :error, :error
45
45
 
46
- # TODO: return array of resources
47
- attribute :resources, array: true, default: -> { [] }
46
+ attribute :resources, :resource, array: true, default: -> { [] }
48
47
  end
49
48
  end
@@ -11,18 +11,21 @@ module HCloud
11
11
  #
12
12
  # == Sort certificates
13
13
  #
14
- # HCloud::Certificate.all.sort(name: :desc)
14
+ # HCloud::Certificate.sort(name: :desc)
15
15
  # # => [#<HCloud::Certificate id: 1, ...>, ...]
16
16
  #
17
- # HCloud::Certificate.all.sort(:id, name: :asc)
17
+ # HCloud::Certificate.sort(:id, name: :asc)
18
18
  # # => [#<HCloud::Certificate id: 1, ...>, ...]
19
19
  #
20
20
  # == Search certificates
21
21
  #
22
- # HCloud::Certificate.all.where(name: "my_certificate")
22
+ # HCloud::Certificate.where(name: "my_certificate")
23
23
  # # => #<HCloud::Certificate id: 1, ...>
24
24
  #
25
- # HCloud::Certificate.all.where(type: "uploaded")
25
+ # HCloud::Certificate.where(type: "uploaded")
26
+ # # => #<HCloud::Certificate id: 1, ...>
27
+ #
28
+ # HCloud::Certificate.where(label_selector: { environment: "production" })
26
29
  # # => #<HCloud::Certificate id: 1, ...>
27
30
  #
28
31
  # == Find certificate by ID
@@ -94,6 +97,7 @@ module HCloud
94
97
  creatable
95
98
  updatable
96
99
  deletable
100
+ labelable
97
101
 
98
102
  attribute :id, :integer
99
103
  attribute :name
@@ -116,8 +120,6 @@ module HCloud
116
120
  # TODO: dynamically return resource classes
117
121
  attribute :used_by, :used_by, array: true, default: -> { [] }
118
122
 
119
- attribute :labels, default: -> { {} }
120
-
121
123
  action :retry
122
124
 
123
125
  def creatable_attributes
@@ -11,7 +11,7 @@ module HCloud
11
11
  #
12
12
  # == Search datacenters
13
13
  #
14
- # HCloud::Datacenter.all.where(name: "fsn1-dc8")
14
+ # HCloud::Datacenter.where(name: "fsn1-dc8")
15
15
  # # => #<HCloud::Datacenter id: 2, ...>
16
16
  #
17
17
  # == Find datacenter by ID
@@ -11,15 +11,18 @@ module HCloud
11
11
  #
12
12
  # == Sort firewalls
13
13
  #
14
- # HCloud::Firewall.all.sort(name: :desc)
14
+ # HCloud::Firewall.sort(name: :desc)
15
15
  # # => [#<HCloud::Firewall id: 1, ...>, ...]
16
16
  #
17
- # HCloud::Firewall.all.sort(:id, name: :asc)
17
+ # HCloud::Firewall.sort(:id, name: :asc)
18
18
  # # => [#<HCloud::Firewall id: 1, ...>, ...]
19
19
  #
20
20
  # == Search firewalls
21
21
  #
22
- # HCloud::Firewall.all.where(name: "my_firewall")
22
+ # HCloud::Firewall.where(name: "my_firewall")
23
+ # # => #<HCloud::Firewall id: 1, ...>
24
+ #
25
+ # HCloud::Firewall.where(label_selector: { environment: "production" })
23
26
  # # => #<HCloud::Firewall id: 1, ...>
24
27
  #
25
28
  # == Find firewall by ID
@@ -107,6 +110,7 @@ module HCloud
107
110
  creatable
108
111
  updatable
109
112
  deletable
113
+ labelable
110
114
 
111
115
  attribute :id, :integer
112
116
  attribute :name
@@ -117,8 +121,6 @@ module HCloud
117
121
 
118
122
  attribute :rules, :rule, array: true, default: -> { [] }
119
123
 
120
- attribute :labels, default: -> { {} }
121
-
122
124
  action :apply_to_resources
123
125
  action :remove_from_resources
124
126
  action :set_rules
@@ -11,15 +11,18 @@ module HCloud
11
11
  #
12
12
  # == Sort floating IPs
13
13
  #
14
- # HCloud::FloatingIP.all.sort(id: :asc)
14
+ # HCloud::FloatingIP.sort(id: :asc)
15
15
  # # => [#<HCloud::FloatingIP id: 1, ...>, ...]
16
16
  #
17
- # HCloud::FloatingIP.all.sort(:id, created: :asc)
17
+ # HCloud::FloatingIP.sort(:id, created: :asc)
18
18
  # # => [#<HCloud::FloatingIP id: 1, ...>, ...]
19
19
  #
20
20
  # == Search floating IPs
21
21
  #
22
- # HCloud::FloatingIP.all.where(name: "my_floating_ip")
22
+ # HCloud::FloatingIP.where(name: "my_floating_ip")
23
+ # # => #<HCloud::FloatingIP id: 1, ...>
24
+ #
25
+ # HCloud::FloatingIP.where(label_selector: { environment: "production" })
23
26
  # # => #<HCloud::FloatingIP id: 1, ...>
24
27
  #
25
28
  # == Find floating IP by ID
@@ -104,6 +107,7 @@ module HCloud
104
107
  creatable
105
108
  updatable
106
109
  deletable
110
+ labelable
107
111
 
108
112
  attribute :id, :integer
109
113
  attribute :name
@@ -121,8 +125,6 @@ module HCloud
121
125
 
122
126
  attribute :server, :server
123
127
 
124
- attribute :labels, default: -> { {} }
125
-
126
128
  alias blocked? blocked
127
129
 
128
130
  action :assign
@@ -11,21 +11,21 @@ module HCloud
11
11
  #
12
12
  # == Sort images
13
13
  #
14
- # HCloud::Image.all.sort(name: :desc)
14
+ # HCloud::Image.sort(name: :desc)
15
15
  # # => [#<HCloud::Image id: 1, ...>, ...]
16
16
  #
17
- # HCloud::Image.all.sort(:id, name: :asc)
17
+ # HCloud::Image.sort(:id, name: :asc)
18
18
  # # => [#<HCloud::Image id: 1, ...>, ...]
19
19
  #
20
20
  # == Search images
21
21
  #
22
- # HCloud::Image.all.where(name: "my_image")
22
+ # HCloud::Image.where(name: "my_image")
23
23
  # # => #<HCloud::Image id: 1, ...>
24
24
  #
25
- # HCloud::Image.all.where(status: "available", include_deprecated: false)
25
+ # HCloud::Image.where(status: "available", include_deprecated: false)
26
26
  # # => #<HCloud::Image id: 1, ...>
27
27
  #
28
- # HCloud::Image.all.where(type: "backup", bound_to: 1)
28
+ # HCloud::Image.where(type: "backup", bound_to: 1)
29
29
  # # => #<HCloud::Image id: 1, ...>
30
30
  #
31
31
  # == Find image by ID
@@ -85,6 +85,7 @@ module HCloud
85
85
  queryable
86
86
  updatable
87
87
  deletable
88
+ labelable
88
89
 
89
90
  attribute :id, :integer
90
91
  attribute :name
@@ -113,8 +114,6 @@ module HCloud
113
114
 
114
115
  attribute :rapid_deploy
115
116
 
116
- attribute :labels, default: -> { {} }
117
-
118
117
  action :change_protection
119
118
 
120
119
  def created?