hcloud 0.1.0.pre.alpha4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e4dbd2d5d61d5bbe1fce20502673f677a67faf33
4
- data.tar.gz: 0ddfe0a2a9a06490c46e843b6ada4a38ab269ceb
3
+ metadata.gz: 42e5e0786794e6040e88021aeec5ea8d0c3da4d8
4
+ data.tar.gz: b2368e1557cecb9e16089cc9a850979b85faae7e
5
5
  SHA512:
6
- metadata.gz: 3e60745c5f5d8692370d00bcab67ec354b2aa7bef9507417851713c58b687c61d274a039ae89635f1f0a4872fb5a376ab03f39fb3878d63f83b8d577f7faf4fe
7
- data.tar.gz: 14ef3b03e95390258c8f1efc42586e97b6624b152cc61278b0f1b3c9cdffbd5fc79c8dd73228bd8df31df0ae3c4ceac1ffdb84ffbcb3364b13b64b8295b973e9
6
+ metadata.gz: 0e885d2e44be9a4bc6750b55c859de56d02059de3611c63c684f7bff51931f8d8ba677f430e7b74fa48b7f1adea837cefd0fb2607d209682b3ba81035b426b41
7
+ data.tar.gz: b582dc6e91e9dccb04cc5469d83a28795f55d3f7ce7d5da0826fe6c8035a58bbc89ef17cf2163b164a1577c6aba4fde4b0d03b6eb325b2a0cca87efd0a4b0f03
data/.gitignore CHANGED
@@ -1,5 +1,6 @@
1
1
  /.bundle/
2
2
  /vendor
3
+ config.ru
3
4
  /.yardoc
4
5
  /Gemfile.lock
5
6
  /_yardoc/
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format=documentation
2
+ --color
3
+ --tty
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ script: "bundle exec rspec"
3
+ sudo: false
4
+ rvm:
5
+ - 2.3
6
+ - 2.4
7
+ - 2.5
data/Gemfile CHANGED
@@ -3,6 +3,7 @@ source "https://rubygems.org"
3
3
  git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  gem 'pry'
6
+ gem 'codecov', :require => false, :group => :test
6
7
 
7
8
  # Specify your gem's dependencies in hcloud.gemspec
8
9
  gemspec
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Hcloud
2
2
 
3
+ [![Build Status](https://travis-ci.org/tonobo/hcloud-ruby.svg?branch=master)](https://travis-ci.org/tonobo/hcloud-ruby)
4
+ [![codecov](https://codecov.io/gh/tonobo/hcloud-ruby/branch/master/graph/badge.svg)](https://codecov.io/gh/tonobo/hcloud-ruby)
5
+
3
6
  This is an unoffical ruby client for HetznerCloud Api service.
4
7
 
5
8
  **Its currently in development and lacking a lot of feature.
@@ -43,11 +46,29 @@ end
43
46
 
44
47
  * Create a server
45
48
 
49
+ Nonblocking:
50
+
46
51
  ```ruby
47
52
  c.servers.create(name: "moo5", server_type: "cx11", image: "ubuntu-16.04")
48
53
  #=> [#<Hcloud::Action>, <#Hcloud::Server>, "root_password"]
49
54
  ```
50
55
 
56
+ Wating for finish:
57
+
58
+ ```ruby
59
+ action,server = c.servers.create(name: "moo5", server_type: "cx11", image: "ubuntu-16.04")
60
+
61
+ while action.status == "running"
62
+ puts "Waiting for Action #{action.id} to complete ..."
63
+ action = c.actions.find(action.id)
64
+ server = c.servers.find(server.id)
65
+ puts "Action Status: #{action.status}"
66
+ puts "Server Status: #{server.status}"
67
+ puts "Server IP Config: #{server.public_net["ipv4"]}"
68
+ sleep 5
69
+ end
70
+ ```
71
+
51
72
  * Update servers' name
52
73
 
53
74
  ```ruby
@@ -21,6 +21,10 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.add_development_dependency "bundler", "~> 1.15"
23
23
  spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "grape"
25
+ spec.add_development_dependency "activesupport"
26
+ spec.add_development_dependency "rspec"
27
+ spec.add_development_dependency "webmock"
24
28
  spec.add_runtime_dependency "typhoeus"
25
29
  spec.add_runtime_dependency "oj"
26
30
  spec.add_runtime_dependency "activesupport"
@@ -5,6 +5,7 @@ module Hcloud
5
5
  autoload :Error, 'hcloud/errors'
6
6
  autoload :Client, 'hcloud/client'
7
7
  autoload :AbstractResource, 'hcloud/abstract_resource'
8
+ autoload :MultiReply, 'hcloud/multi_reply'
8
9
  autoload :ServerResource, 'hcloud/server_resource'
9
10
  autoload :EntryLoader, 'hcloud/entry_loader'
10
11
  autoload :FloatingIP, 'hcloud/floating_ip'
@@ -24,4 +25,5 @@ module Hcloud
24
25
  autoload :ActionResource, 'hcloud/action_resource'
25
26
  autoload :Iso, 'hcloud/iso'
26
27
  autoload :IsoResource, 'hcloud/iso_resource'
28
+ autoload :Pagination, 'hcloud/pagination'
27
29
  end
@@ -1,12 +1,66 @@
1
1
  module Hcloud
2
2
  class AbstractResource
3
+ include Enumerable
4
+
3
5
  attr_reader :client, :parent, :base_path
4
6
 
5
7
  def initialize(client:, parent: nil, base_path: "")
6
8
  @client = client
7
9
  @parent = parent
10
+ @page = 1
11
+ @per_page = 25
12
+ @order = []
8
13
  @base_path = base_path
9
14
  end
15
+
16
+ def page(page)
17
+ @page = page
18
+ self
19
+ end
20
+
21
+ def per_page(per_page)
22
+ @per_page = per_page
23
+ self
24
+ end
25
+
26
+ def limit(limit)
27
+ @limit = limit
28
+ self
29
+ end
30
+
31
+ def order(*sort)
32
+ @order = sort.flat_map do |s|
33
+ case s
34
+ when Symbol, String then s.to_s
35
+ when Hash then s.map { |k, v| "#{k}:#{v}" }
36
+ else
37
+ raise ArgumentError,
38
+ "Unable to resolve type for given #{s.inspect} from #{sort}"
39
+ end
40
+ end
41
+ self
42
+ end
43
+
44
+ def mj(path, **o, &block)
45
+ if !client.nil? and client.auto_pagination
46
+ requests = __entries__(path, **o)
47
+ if requests.all?{|x| x.is_a? Hash }
48
+ m = MultiReply.new(j: requests, pagination: :auto)
49
+ m.cb = block
50
+ return m
51
+ end
52
+ client.hydra.run
53
+ j = requests.map do |x|
54
+ Oj.load(x.response.body)
55
+ end
56
+ m = MultiReply.new(j: j, pagination: :auto)
57
+ m.cb = block
58
+ return m
59
+ end
60
+ m = MultiReply.new(j: [Oj.load(request(path, o.merge(ep: ep)).run.body)])
61
+ m.cb = block
62
+ m
63
+ end
10
64
 
11
65
  def each(&block)
12
66
  all.each do |member|
@@ -16,8 +70,44 @@ module Hcloud
16
70
 
17
71
  protected
18
72
 
73
+ def page_params(per_page: nil, page: nil)
74
+ { per_page: per_page || @per_page, page: page || @page }.to_param
75
+ end
76
+
77
+ def sort_params
78
+ @order.to_a.map{|x| "sort=#{x}" }.join("&")
79
+ end
80
+
81
+ def ep(per_page: nil, page: nil)
82
+ r = []
83
+ (x = page_params(per_page: per_page, page: page)).empty? ? nil : r << x
84
+ (x = sort_params).empty? ? nil : r << x
85
+ r.compact.join("&")
86
+ end
87
+
19
88
  def request(*args)
20
89
  client.request(*args)
21
90
  end
91
+
92
+ def __entries__(path, **o)
93
+ ret = Oj.load(request(path, o.merge(ep: ep(per_page: 1, page: 1))).run.body)
94
+ a = ret.dig("meta", "pagination", "total_entries").to_i
95
+ if a <= 1
96
+ return [ret]
97
+ end
98
+ unless @limit.nil?
99
+ a = @limit if a > @limit
100
+ end
101
+ r = a / Client::MAX_ENTRIES_PER_PAGE + (a % Client::MAX_ENTRIES_PER_PAGE)
102
+ requests = r.times.map do |i|
103
+ per_page = Client::MAX_ENTRIES_PER_PAGE
104
+ if !@limit.nil? and r == (i+1) and a % per_page != 0
105
+ per_page = a % per_page
106
+ end
107
+ req = request(path, o.merge(ep: ep(per_page: per_page, page: i+1)))
108
+ client.hydra.queue req
109
+ req
110
+ end
111
+ end
22
112
  end
23
113
  end
@@ -1,14 +1,12 @@
1
1
 
2
2
  module Hcloud
3
3
  class ActionResource < AbstractResource
4
- include Enumerable
5
-
6
- def all(sort: nil)
7
- Oj.load(request(base_path("actions"), q: {sort: sort}).run.body)["actions"].map do |x|
8
- Action.new(x, self, client)
4
+ def all
5
+ mj(base_path("actions")) do |j|
6
+ j.flat_map{|x| x["actions"].map{ |x| Action.new(x, self, client) } }
9
7
  end
10
8
  end
11
-
9
+
12
10
  def find(id)
13
11
  Action.new(
14
12
  Oj.load(request(base_path("actions/#{id.to_i}")).run.body)["action"],
@@ -22,12 +20,9 @@ module Hcloud
22
20
  rescue Error::NotFound
23
21
  end
24
22
 
25
- def where(status: nil, sort: nil)
26
- Oj.load(
27
- request(base_path("actions"),
28
- q: {status: status, sort: sort}).run.body
29
- )["actions"].map do |x|
30
- Action.new(x, self, client)
23
+ def where(status: nil)
24
+ mj(base_path("actions"), q: {status: status}) do |j|
25
+ j.flat_map{|x| x["actions"].map{ |x| Action.new(x, self, client) }}
31
26
  end
32
27
  end
33
28
 
@@ -3,9 +3,14 @@ autoload :Oj, "oj"
3
3
 
4
4
  module Hcloud
5
5
  class Client
6
- attr_reader :token
7
- def initialize(token:)
6
+ MAX_ENTRIES_PER_PAGE = 50
7
+
8
+ attr_reader :token, :auto_pagination, :hydra
9
+ def initialize(token:, auto_pagination: false, concurrency: 20)
8
10
  @token = token
11
+ @auto_pagination = auto_pagination
12
+ @concurrency = concurrency
13
+ @hydra = Typhoeus::Hydra.new(max_concurrency: concurrency)
9
14
  end
10
15
 
11
16
  def authorized?
@@ -57,9 +62,13 @@ module Hcloud
57
62
  options[:body] = Oj.dump(x, mode: :compat)
58
63
  options[:method] ||= :post
59
64
  end
65
+ q = []
66
+ q << options.delete(:ep).to_s
60
67
  if x = options.delete(:q)
61
- path << "?"+x.to_param
68
+ q << x.to_param
62
69
  end
70
+ path = path.dup
71
+ path << "?"+q.join("&")
63
72
  r = Typhoeus::Request.new(
64
73
  "https://api.hetzner.cloud/v1/#{path}",
65
74
  {
@@ -34,7 +34,7 @@ module Hcloud
34
34
  )
35
35
  end
36
36
 
37
- def destory
37
+ def destroy
38
38
  request("images/#{id.to_i}", method: :delete).run
39
39
  true
40
40
  end
@@ -1,10 +1,8 @@
1
1
  module Hcloud
2
2
  class ImageResource < AbstractResource
3
- include Enumerable
4
-
5
3
  def all
6
- Oj.load(request("images").run.body)["images"].map do |x|
7
- Image.new(x, self, client)
4
+ mj("images") do |j|
5
+ j.flat_map{|x| x["images"].map{ |x| Image.new(x, self, client) } }
8
6
  end
9
7
  end
10
8
 
@@ -33,10 +31,8 @@ module Hcloud
33
31
  method(:where).parameters.inject(query) do |r,x|
34
32
  (var = eval(x.last.to_s)).nil? ? r : r.merge!(x.last => var)
35
33
  end
36
- Oj.load(
37
- request("images", q: query).run.body
38
- )["images"].map do |x|
39
- Image.new(x, self, client)
34
+ mj("images", q: query) do |j|
35
+ j.flat_map{|x| x["images"].map{ |x| Image.new(x, self, client) } }
40
36
  end
41
37
  end
42
38
 
@@ -1,10 +1,8 @@
1
1
  module Hcloud
2
2
  class IsoResource < AbstractResource
3
- include Enumerable
4
-
5
3
  def all
6
- Oj.load(request("isos").run.body)["isos"].map do |x|
7
- Iso.new(x, self, client)
4
+ mj("isos") do |j|
5
+ j.flat_map{|x| x["isos"].map{ |x| Iso.new(x, self, client) } }
8
6
  end
9
7
  end
10
8
 
@@ -1,10 +1,9 @@
1
1
  module Hcloud
2
2
  class LocationResource < AbstractResource
3
- include Enumerable
4
-
5
3
  def all
6
- j = Oj.load(request("locations").run.body)
7
- j["locations"].map{|x| Location.new(x, self, client) }
4
+ mj("locations") do |j|
5
+ j.flat_map{|x| x["locations"].map{ |x| Location.new(x, self, client) } }
6
+ end
8
7
  end
9
8
 
10
9
  def find(id)
@@ -0,0 +1,22 @@
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(&block)
16
+ @cb.call(@j).each do |member|
17
+ block.call(member)
18
+ end
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ module Hcloud
2
+ class Pagination
3
+ Attributes = {
4
+ page: nil,
5
+ per_page: nil,
6
+ previous_page: nil,
7
+ next_page: nil,
8
+ last_page: nil,
9
+ total_entries: nil,
10
+ }
11
+
12
+ include EntryLoader
13
+ end
14
+ end
@@ -1,7 +1,5 @@
1
1
  module Hcloud
2
2
  class ServerResource < AbstractResource
3
- include Enumerable
4
-
5
3
  def create(name:,
6
4
  server_type:,
7
5
  datacenter: nil,
@@ -23,8 +21,8 @@ module Hcloud
23
21
  end
24
22
 
25
23
  def all
26
- Oj.load(request("servers").run.body)["servers"].map do |x|
27
- Server.new(x, self, client)
24
+ mj("servers") do |j|
25
+ j.flat_map{|x| x["servers"].map{ |x| Server.new(x, self, client) } }
28
26
  end
29
27
  end
30
28
 
@@ -1,15 +1,14 @@
1
1
  module Hcloud
2
2
  class SSHKeyResource < AbstractResource
3
- include Enumerable
4
-
5
3
  def all
6
- j = Oj.load(request("ssh_keys").run.body)
7
- j["ssh_keys"].map{|x| SSHKey.new(x, self, client) }
4
+ mj("ssh_keys") do |j|
5
+ j.flat_map{|x| x["ssh_keys"].map{ |x| SSHKey.new(x, self, client) } }
6
+ end
8
7
  end
9
8
 
10
9
  def create(name:, public_key:)
11
10
  j = Oj.load(request("ssh_keys", j: {name: name, public_key: public_key}).run.body)
12
- SSHKey.new(j, self, client)
11
+ SSHKey.new(j["ssh_key"], self, client)
13
12
  end
14
13
 
15
14
  def find(id)
@@ -1,3 +1,3 @@
1
1
  module Hcloud
2
- VERSION = "0.1.0-alpha4"
2
+ VERSION = "0.1.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hcloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre.alpha4
4
+ version: 0.1.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-01-30 00:00:00.000000000 Z
11
+ date: 2018-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,6 +38,62 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: grape
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activesupport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: webmock
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
41
97
  - !ruby/object:Gem::Dependency
42
98
  name: typhoeus
43
99
  requirement: !ruby/object:Gem::Requirement
@@ -88,6 +144,8 @@ extensions: []
88
144
  extra_rdoc_files: []
89
145
  files:
90
146
  - ".gitignore"
147
+ - ".rspec"
148
+ - ".travis.yml"
91
149
  - Gemfile
92
150
  - README.md
93
151
  - Rakefile
@@ -111,6 +169,8 @@ files:
111
169
  - lib/hcloud/iso_resource.rb
112
170
  - lib/hcloud/location.rb
113
171
  - lib/hcloud/location_resource.rb
172
+ - lib/hcloud/multi_reply.rb
173
+ - lib/hcloud/pagination.rb
114
174
  - lib/hcloud/server.rb
115
175
  - lib/hcloud/server_resource.rb
116
176
  - lib/hcloud/server_type.rb
@@ -132,9 +192,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
132
192
  version: '0'
133
193
  required_rubygems_version: !ruby/object:Gem::Requirement
134
194
  requirements:
135
- - - ">"
195
+ - - ">="
136
196
  - !ruby/object:Gem::Version
137
- version: 1.3.1
197
+ version: '0'
138
198
  requirements: []
139
199
  rubyforge_project:
140
200
  rubygems_version: 2.5.2.2