hcloud 0.1.2 → 1.0.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 (44) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +0 -1
  3. data/.rubocop.yml +24 -9
  4. data/.rubocop_todo.yml +18 -121
  5. data/.travis.yml +3 -3
  6. data/CHANGELOG.md +13 -0
  7. data/Gemfile +3 -0
  8. data/Gemfile.lock +143 -0
  9. data/README.md +34 -1
  10. data/Rakefile +2 -0
  11. data/bin/console +1 -0
  12. data/hcloud.gemspec +5 -3
  13. data/lib/hcloud.rb +31 -5
  14. data/lib/hcloud/abstract_resource.rb +162 -55
  15. data/lib/hcloud/action.rb +8 -10
  16. data/lib/hcloud/action_resource.rb +3 -29
  17. data/lib/hcloud/client.rb +66 -28
  18. data/lib/hcloud/datacenter.rb +7 -7
  19. data/lib/hcloud/datacenter_resource.rb +6 -31
  20. data/lib/hcloud/entry_loader.rb +181 -20
  21. data/lib/hcloud/errors.rb +2 -0
  22. data/lib/hcloud/floating_ip.rb +18 -29
  23. data/lib/hcloud/floating_ip_resource.rb +15 -30
  24. data/lib/hcloud/image.rb +12 -32
  25. data/lib/hcloud/image_resource.rb +7 -38
  26. data/lib/hcloud/iso.rb +4 -1
  27. data/lib/hcloud/iso_resource.rb +7 -28
  28. data/lib/hcloud/location.rb +3 -9
  29. data/lib/hcloud/location_resource.rb +6 -27
  30. data/lib/hcloud/network.rb +33 -0
  31. data/lib/hcloud/network_resource.rb +25 -0
  32. data/lib/hcloud/pagination.rb +2 -9
  33. data/lib/hcloud/server.rb +37 -70
  34. data/lib/hcloud/server_resource.rb +16 -36
  35. data/lib/hcloud/server_type.rb +3 -10
  36. data/lib/hcloud/server_type_resource.rb +6 -28
  37. data/lib/hcloud/ssh_key.rb +6 -17
  38. data/lib/hcloud/ssh_key_resource.rb +13 -32
  39. data/lib/hcloud/typhoeus_ext.rb +112 -0
  40. data/lib/hcloud/version.rb +3 -1
  41. data/lib/hcloud/volume.rb +32 -0
  42. data/lib/hcloud/volume_resource.rb +29 -0
  43. metadata +31 -13
  44. data/lib/hcloud/multi_reply.rb +0 -21
@@ -1,15 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Hcloud
2
4
  class ServerType
3
- Attributes = {
4
- id: nil,
5
- name: nil,
6
- description: nil,
7
- cores: nil,
8
- memory: nil,
9
- disk: nil,
10
- prices: nil,
11
- storage_type: nil
12
- }.freeze
5
+ require 'hcloud/server_type_resource'
13
6
 
14
7
  include EntryLoader
15
8
  end
@@ -1,37 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Hcloud
2
4
  class ServerTypeResource < AbstractResource
3
- include Enumerable
4
-
5
- def all
6
- j = Oj.load(request('server_types').run.body)
7
- j['server_types'].map { |x| ServerType.new(x, self, client) }
8
- end
5
+ filter_attributes :name
9
6
 
10
- def find(id)
11
- ServerType.new(
12
- Oj.load(request("server_types/#{id}").run.body)['server_type'],
13
- self,
14
- client
15
- )
16
- end
17
-
18
- def find_by(name:)
19
- x = Oj.load(request('server_types', q: { name: name }).run.body)['server_types']
20
- return nil if x.none?
21
- x.each do |s|
22
- return ServerType.new(s, self, client)
23
- end
24
- end
7
+ bind_to ServerType
25
8
 
26
9
  def [](arg)
27
10
  case arg
28
- when Integer
29
- begin
30
- find(arg)
31
- rescue Error::NotFound
32
- end
33
- when String
34
- find_by(name: arg)
11
+ when Integer then find_by(id: arg)
12
+ when String then find_by(name: arg)
35
13
  end
36
14
  end
37
15
  end
@@ -1,23 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Hcloud
2
4
  class SSHKey
3
- Attributes = {
4
- id: nil,
5
- name: nil,
6
- fingerprint: nil,
7
- public_key: nil
8
- }.freeze
9
- include EntryLoader
5
+ require 'hcloud/ssh_key_resource'
10
6
 
11
- def update(name:)
12
- j = Oj.load(request("ssh_keys/#{id.to_i}",
13
- j: { name: name },
14
- method: :put).run.body)
15
- SSHKey.new(j['ssh_key'], self, client)
16
- end
7
+ include EntryLoader
17
8
 
18
- def destroy
19
- request("ssh_keys/#{id}", method: :delete).run.body
20
- true
21
- end
9
+ updatable :name
10
+ destructible
22
11
  end
23
12
  end
@@ -1,41 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Hcloud
2
4
  class SSHKeyResource < AbstractResource
3
- def all
4
- mj('ssh_keys') do |j|
5
- j.flat_map { |x| x['ssh_keys'].map { |x| SSHKey.new(x, self, client) } }
6
- end
7
- end
5
+ filter_attributes :name
8
6
 
9
- def create(name:, public_key:)
10
- j = Oj.load(request('ssh_keys', j: { name: name, public_key: public_key }).run.body)
11
- SSHKey.new(j['ssh_key'], self, client)
12
- end
13
-
14
- def find(id)
15
- SSHKey.new(
16
- Oj.load(request("ssh_keys/#{id}").run.body)['ssh_key'],
17
- self,
18
- client
19
- )
20
- end
21
-
22
- def find_by(name:)
23
- x = Oj.load(request('ssh_keys', q: { name: name }).run.body)['ssh_keys']
24
- return nil if x.none?
25
- x.each do |s|
26
- return SSHKey.new(s, self, client)
7
+ def [](arg)
8
+ case arg
9
+ when Integer then find_by(id: arg)
10
+ when String then find_by(name: arg)
27
11
  end
28
12
  end
29
13
 
30
- def [](arg)
31
- case arg
32
- when Integer
33
- begin
34
- find(arg)
35
- rescue Error::NotFound
36
- end
37
- when String
38
- find_by(name: arg)
14
+ def create(name:, public_key:)
15
+ prepare_request(
16
+ 'ssh_keys', j: COLLECT_ARGS.call(__method__, binding),
17
+ expected_code: 201
18
+ ) do |response|
19
+ SSHKey.new(client, response.parsed_json[:ssh_key])
39
20
  end
40
21
  end
41
22
  end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/hash/indifferent_access'
4
+
5
+ module Hcloud
6
+ module TyphoeusExt
7
+ Context = Struct.new(:client)
8
+
9
+ ATTRIBUTES = %i[
10
+ block autoload_action resource_path
11
+ resource_class expected_code
12
+ ].freeze
13
+
14
+ attr_accessor(*ATTRIBUTES)
15
+
16
+ def self.collect_attributes(kwargs)
17
+ hash = {}
18
+ ATTRIBUTES.each do |key|
19
+ hash[key] = kwargs.delete(key) if kwargs.key?(key)
20
+ end
21
+ hash
22
+ end
23
+
24
+ def attributes=(kwargs)
25
+ kwargs.each do |key, value|
26
+ public_send("#{key}=", value)
27
+ end
28
+ end
29
+
30
+ def parsed_json
31
+ return {} if code == 204
32
+
33
+ @parsed_json ||= begin
34
+ Oj.load(body, symbol_keys: true).tap do |json|
35
+ next unless request.hydra
36
+
37
+ check_for_error(
38
+ e_code: json.to_h.dig(:error, :code),
39
+ e_message: json.to_h.dig(:error, :message)
40
+ )
41
+ end
42
+ end
43
+ rescue StandardError
44
+ raise Error::UnexpectedError, "unable to load body: #{body}"
45
+ end
46
+
47
+ def context
48
+ @context ||= Context.new
49
+ end
50
+
51
+ def check_for_error(e_code: nil, e_message: nil)
52
+ case code
53
+ when 401 then raise(Error::Unauthorized)
54
+ when 0 then raise(Error::ServerError, "Connection error: #{return_code}")
55
+ when 400...600
56
+ raise _error_class(e_code || error_code), e_message || error_message
57
+ end
58
+
59
+ raise Error::UnexpectedError, body if expected_code && expected_code != code
60
+ end
61
+
62
+ def pagination
63
+ @pagination ||= Pagination.new(parsed_json[:meta].to_h[:pagination])
64
+ end
65
+
66
+ def resource_attributes
67
+ _resource = [@resource_path].flatten.compact.map(&:to_s).map(&:to_sym)
68
+ return parsed_json if _resource.empty?
69
+
70
+ parsed_json.dig(*_resource)
71
+ end
72
+
73
+ def [](arg)
74
+ parsed_json[arg]
75
+ end
76
+
77
+ def resource
78
+ action = parsed_json[:action] if autoload_action
79
+ return [Action.new(self, action), block.call(self)].flatten(1) if block && action
80
+ return block.call(self) if block
81
+
82
+ @resource_class.from_response(self, autoload_action: autoload_action)
83
+ end
84
+
85
+ def error_code
86
+ error[:code]
87
+ end
88
+
89
+ def error_message
90
+ error[:message]
91
+ end
92
+
93
+ def error
94
+ parsed_json[:error].to_h
95
+ end
96
+
97
+ def _error_class(code)
98
+ case code
99
+ when 'invalid_input' then Error::InvalidInput
100
+ when 'forbidden' then Error::Forbidden
101
+ when 'locked' then Error::Locked
102
+ when 'not_found' then Error::NotFound
103
+ when 'rate_limit_exceeded' then Error::RateLimitExceeded
104
+ when 'resource_unavailable' then Error::ResourceUnavailable
105
+ when 'service_error' then Error::ServiceError
106
+ when 'uniqueness_error' then Error::UniquenessError
107
+ else
108
+ Error::ServerError
109
+ end
110
+ end
111
+ end
112
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Hcloud
2
- VERSION = '0.1.2'.freeze
4
+ VERSION = '1.0.0'
3
5
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hcloud
4
+ class Volume
5
+ require 'hcloud/volume_resource'
6
+
7
+ include EntryLoader
8
+
9
+ schema(
10
+ created: :time,
11
+ location: Location
12
+ )
13
+
14
+ protectable :delete
15
+ updatable :name
16
+ destructible
17
+
18
+ has_actions
19
+
20
+ def attach(server:, automount:)
21
+ prepare_request('actions/attach', j: COLLECT_ARGS.call(__method__, binding))
22
+ end
23
+
24
+ def detach
25
+ prepare_request('actions/detach', method: :post)
26
+ end
27
+
28
+ def resize(size:)
29
+ prepare_request('actions/resize', j: COLLECT_ARGS.call(__method__, binding))
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hcloud
4
+ class VolumeResource < AbstractResource
5
+ filter_attributes :name
6
+
7
+ def [](arg)
8
+ case arg
9
+ when Integer then find_by(id: arg)
10
+ when String then find_by(name: arg)
11
+ end
12
+ end
13
+
14
+ def create(size:, name:, automount: nil, format: nil, location: nil, server: nil)
15
+ prepare_request(
16
+ 'volumes', j: COLLECT_ARGS.call(__method__, binding),
17
+ expected_code: 201
18
+ ) do |response|
19
+ [
20
+ Action.new(client, response.parsed_json[:action]),
21
+ Volume.new(client, response.parsed_json[:volume]),
22
+ response.parsed_json[:next_actions].map do |action|
23
+ Action.new(client, action)
24
+ end
25
+ ]
26
+ end
27
+ end
28
+ end
29
+ end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hcloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Foerster
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-02-27 00:00:00.000000000 Z
11
+ date: 2020-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activemodel
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: activesupport
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -28,16 +42,16 @@ dependencies:
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
- - - "~>"
45
+ - - ">="
32
46
  - !ruby/object:Gem::Version
33
- version: '1.15'
47
+ version: '0'
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
- - - "~>"
52
+ - - ">="
39
53
  - !ruby/object:Gem::Version
40
- version: '1.15'
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: grape
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -56,16 +70,16 @@ dependencies:
56
70
  name: rake
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
- - - "~>"
73
+ - - ">="
60
74
  - !ruby/object:Gem::Version
61
- version: '10.0'
75
+ version: '0'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
- - - "~>"
80
+ - - ">="
67
81
  - !ruby/object:Gem::Version
68
- version: '10.0'
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rspec
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +164,7 @@ files:
150
164
  - ".travis.yml"
151
165
  - CHANGELOG.md
152
166
  - Gemfile
167
+ - Gemfile.lock
153
168
  - README.md
154
169
  - Rakefile
155
170
  - bin/console
@@ -172,7 +187,8 @@ files:
172
187
  - lib/hcloud/iso_resource.rb
173
188
  - lib/hcloud/location.rb
174
189
  - lib/hcloud/location_resource.rb
175
- - lib/hcloud/multi_reply.rb
190
+ - lib/hcloud/network.rb
191
+ - lib/hcloud/network_resource.rb
176
192
  - lib/hcloud/pagination.rb
177
193
  - lib/hcloud/server.rb
178
194
  - lib/hcloud/server_resource.rb
@@ -180,7 +196,10 @@ files:
180
196
  - lib/hcloud/server_type_resource.rb
181
197
  - lib/hcloud/ssh_key.rb
182
198
  - lib/hcloud/ssh_key_resource.rb
199
+ - lib/hcloud/typhoeus_ext.rb
183
200
  - lib/hcloud/version.rb
201
+ - lib/hcloud/volume.rb
202
+ - lib/hcloud/volume_resource.rb
184
203
  homepage: https://github.com/tonobo/hcloud
185
204
  licenses: []
186
205
  metadata: {}
@@ -199,8 +218,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
199
218
  - !ruby/object:Gem::Version
200
219
  version: '0'
201
220
  requirements: []
202
- rubyforge_project:
203
- rubygems_version: 2.5.2.2
221
+ rubygems_version: 3.1.2
204
222
  signing_key:
205
223
  specification_version: 4
206
224
  summary: HetznerCloud native Ruby client
@@ -1,21 +0,0 @@
1
- module Hcloud
2
- class MultiReply
3
- include Enumerable
4
- attr_accessor :cb
5
-
6
- def initialize(j:, pagination: nil)
7
- @j = j
8
- @pagination = pagination
9
- end
10
-
11
- def pagination
12
- @pagination || Pagination.new(@j.first.to_h['meta'].to_h['pagination'], nil, nil)
13
- end
14
-
15
- def each
16
- @cb.call(@j).each do |member|
17
- yield(member)
18
- end
19
- end
20
- end
21
- end