tiktalik 1.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e206091adbcab3e9d09e4f58b6f2822359748cd4
4
+ data.tar.gz: 7caa889c4ea3147e5e4bc035bdbeb3b570dbdbc1
5
+ SHA512:
6
+ metadata.gz: f6ba39ac1c5d87cde7d67cca557f37278fac439bb00b146893fe12fa1b590e5936a39621d2aab5a543122a669ed3f0ae540e28f646accf951eac9934e4641873
7
+ data.tar.gz: 3e2805c2b6556b874d951bbba3d5d930d577a106246f3c1563b162fa07e592c10d47c628ee70a91b91d484cfc7b4aa65b9a5b6d53e33464b4de2b7511c61cea2
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ Gemfile.lock
2
+ pkg/*.gem
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+ script: "bundle exec rake spec"
3
+ rvm:
4
+ - 1.8.7
5
+ - 1.9.2
6
+ - 1.9.3
7
+ - 2.0.0
8
+ - jruby-18mode
9
+ - jruby-19mode
10
+ - rbx-18mode
11
+ - rbx-19mode
12
+ - ree
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem 'rake'
6
+ gem 'rspec', '~> 2.11'
7
+ gem 'oj'
8
+ gem 'timecop'
data/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # Tiktalik Cloud Computing Platform SDK for Ruby
2
+
3
+ Tiktalik SDK for Ruby enables developers using the Ruby programming
4
+ language to access core features of the [Tiktalik Cloud Computing](http://www.tiktalik.com) Platform.
5
+
6
+ The SDK features:
7
+
8
+ * retrieving detailed information on user's instances: recent operations,
9
+ running state, hourly cost etc.
10
+ * core operations on an instance: creating, starting, stopping, starting backup
11
+ * adding and removing network interfaces
12
+ * listing and manipulating backups
13
+ * listing and manipulating networks
14
+
15
+ More cool features coming soon!
16
+
17
+ ## Installation
18
+
19
+
20
+ `$ gem install tiktalik`
21
+
22
+ ## Requirements
23
+
24
+ * [faraday](https://rubygems.org/gems/faraday)
25
+ * [multi_json](https://rubygems.org/gems/multi_json)
26
+
27
+ ## Documentation
28
+
29
+ See [http://www.tiktalik.com/api](http://www.tiktalik.com/api) for documentation and tutorials.
30
+
31
+ ## License
32
+
33
+ Copyright (c) 2013 Rebased s.c.
34
+
35
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
36
+ this software and associated documentation files (the "Software"), to deal in
37
+ the Software without restriction, including without limitation the rights to
38
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
39
+ the Software, and to permit persons to whom the Software is furnished to do so,
40
+ subject to the following conditions:
41
+
42
+ The above copyright notice and this permission notice shall be included in all
43
+ copies or substantial portions of the Software.
44
+
45
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
46
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
47
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
48
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
49
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
50
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new do |t|
7
+ t.rspec_opts = ["-c", "-f progress"]
8
+ t.pattern = 'spec/**/*_spec.rb'
9
+ end
10
+
11
+ task :default => :spec
@@ -0,0 +1,118 @@
1
+ # Represents a user's Instance. This object is used to perform mission-critical
2
+ # operations like stopping or starting an instance. Note that you should never
3
+ # construct this object yourself; use a ComputingConnection to fetch instances
4
+ # from the server.
5
+ module Tiktalik
6
+ module Computing
7
+ class Instance < Object
8
+
9
+ attr_reader :uuid, # String
10
+ :hostname, # String
11
+ :owner, # String
12
+ :vpsimage_uuid, # String
13
+ :state, # Fixnum
14
+ :running, # Boolean
15
+ :interfaces, # Array(VPSNetInterface)
16
+ :actions, # Array(Operation)
17
+ :vpsimage, # VPSImage
18
+ :default_password, # String
19
+ :service_name, # String
20
+ :gross_cost_per_hour # Float
21
+
22
+ # List of user virtual machines.
23
+ #
24
+ # @param [Hash] params Params for results
25
+ #
26
+ # @option params [Boolean] :actions Include list of recent operations if true.
27
+ # @option params [Boolean] :vpsimage Include details about source image if true.
28
+ # @option params [Boolean] :cost Include current cost per hour for each instance if true.
29
+ def self.all(params = {})
30
+ results = request(:get, '/computing/instance', params)
31
+ results.collect { |result| new(result) }
32
+ end
33
+
34
+ # Create a new virtual machine.
35
+ #
36
+ # @param [Hash] params Params for instance
37
+ #
38
+ # @option params [String] :image_uuid UID of disk image that should be used(required)
39
+ # @option params [String] :size Size of instance in Units(required)
40
+ # @option params [String] :hostname Hostname set at installation time(required)
41
+ # @option params [Array] :networks Networks to attach, each one as "{uuid}" from Network model.
42
+ def self.create(params = {})
43
+ require_params(params, :image_uuid, :size, :hostname)
44
+ result = request(:post, '/computing/instance', params)
45
+ new(result)
46
+ end
47
+
48
+ # Get virtual machine details.
49
+ #
50
+ # @param [String] uuid UUID of instance
51
+ def self.find(uuid)
52
+ result = request(:get, "/computing/instance/#{uuid}")
53
+ new(result)
54
+ end
55
+
56
+ # Delete instance.
57
+ def destroy
58
+ request(:delete, "/computing/instance/#{@uuid}")
59
+ true
60
+ end
61
+
62
+ # Create virtual machine network interface.
63
+ #
64
+ # @param [Hash] params Params for interface
65
+ #
66
+ # @option params [String] :network_uuid Network UUID. The interface will be assigned an address in this network(required)
67
+ # @option params [String] :seq Interface number, eg. '3' maps to eth3(required)
68
+ def build_interface(params = {})
69
+ require_params(params, :network_uuid, :seq)
70
+ result = request(:post, "/computing/instance/#{@uuid}/interface", params)
71
+ VPSNetInterface.new(result)
72
+ end
73
+
74
+ # Call "Install" operation on virtual machine.
75
+ def install
76
+ request(:post, "/computing/instance/#{@uuid}/install")
77
+ true
78
+ end
79
+
80
+ # Call "Boot" or "Start" operation on virtual machine.
81
+ def start
82
+ request(:post, "/computing/instance/#{@uuid}/start")
83
+ true
84
+ end
85
+
86
+ # Call "Shutdown" operation on virtual machine.
87
+ def stop
88
+ request(:post, "/computing/instance/#{@uuid}/stop")
89
+ true
90
+ end
91
+
92
+ # Force "Shutdown" operation on virtual machine.
93
+ def force_stop
94
+ request(:post, "/computing/instance/#{@uuid}/force_stop")
95
+ true
96
+ end
97
+
98
+ # Do "Backup" of virtual machine. VPS need to be stopped in order to create its backup.
99
+ def backup
100
+ request(:post, "/computing/instance/#{@uuid}/backup")
101
+ true
102
+ end
103
+
104
+ private
105
+
106
+ def after_initialize
107
+ @interfaces = [] unless @interfaces.is_a?(Array)
108
+ @interfaces.collect! { |interface| interface.is_a?(VPSNetInterface) ? interface : VPSNetInterface.new(interface.merge(:instance_uuid => @uuid)) }
109
+
110
+ @actions = [] unless @actions.is_a?(Array)
111
+ @actions.collect! { |action| action.is_a?(Operation) ? action : Operation.new(action) }
112
+
113
+ @vpsimage = VPSImage.new(@vpsimage) if @vpsimage
114
+ end
115
+
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,42 @@
1
+ # A user- or system-owned network. Each Instance has zero or more networks
2
+ # attached, each networking interfaces is represented by a VPSNetInterface
3
+ # object.
4
+ module Tiktalik
5
+ module Computing
6
+ class Network < Object
7
+
8
+ attr_reader :uuid, # String
9
+ :name, # String
10
+ :net, # String
11
+ :owner, # String
12
+ :domainname, # String
13
+ :public # Boolean
14
+
15
+ # List of available networks.
16
+ def self.all
17
+ results = request(:get, '/computing/network')
18
+ results.collect { |result| new(result) }
19
+ end
20
+
21
+ # Create private network.
22
+ #
23
+ # @param [Hash] params Params for network
24
+ #
25
+ # @option params [String] :name Network name - as part of local domain(required)
26
+ def self.create(params = {})
27
+ require_params(params, :name)
28
+ result = request(:post, '/computing/network', params)
29
+ new(result)
30
+ end
31
+
32
+ # Get network.
33
+ #
34
+ # @param [String] uuid UUID of network
35
+ def self.find(uuid)
36
+ result = request(:get, "/computing/network/#{uuid}")
37
+ new(result)
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,22 @@
1
+ # Description of an operation that was performed on an Instance.
2
+ # Used purely for informative purposes.
3
+ module Tiktalik
4
+ module Computing
5
+ class Operation < Object
6
+
7
+ attr_reader :uuid, # String
8
+ :start_time, # Time
9
+ :end_time, # Time
10
+ :description, # String
11
+ :progress # Fixnum
12
+
13
+ private
14
+
15
+ def after_initialize
16
+ @start_time = Time.parse(@start_time) if @start_time
17
+ @end_time = Time.parse(@end_time) if @end_time
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,42 @@
1
+ # Disk image that can be used to create a new instance, or restore one from backup.
2
+ module Tiktalik
3
+ module Computing
4
+ class VPSImage < Object
5
+
6
+ attr_reader :uuid, # String
7
+ :name, # String
8
+ :owner, # String
9
+ :type, # String - 'backup', 'image' or 'install'
10
+ :is_public, # Boolean
11
+ :description, # String
12
+ :create_time # Time
13
+
14
+ # List of VPS images.
15
+ def self.all
16
+ results = request(:get, '/computing/image')
17
+ results.collect { |result| new(result) }
18
+ end
19
+
20
+ # Get image or backup.
21
+ #
22
+ # @param [String] uuid UUID of image
23
+ def self.find(uuid)
24
+ result = request(:get, "/computing/image/#{uuid}")
25
+ new(result)
26
+ end
27
+
28
+ # Delete users backup image.
29
+ def destroy
30
+ request(:delete, "/computing/image/#{uuid}")
31
+ true
32
+ end
33
+
34
+ private
35
+
36
+ def after_initialize
37
+ @create_time = Time.parse(@create_time) if @create_time
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,27 @@
1
+ # A network interface attached to an Instance. Maps directly to a network interface
2
+ # visible from the operating system's point.
3
+ module Tiktalik
4
+ module Computing
5
+ class VPSNetInterface < Object
6
+
7
+ attr_reader :uuid, # String
8
+ :network, # Network
9
+ :mac, # String
10
+ :ip, # String
11
+ :seq # Fixnum - interface sequence number: 0 for eth0, 1 for eth1, etc.
12
+
13
+ # Remove virtual machine network interface.
14
+ def destroy
15
+ request(:delete, "/computing/instance/#{@instance_uuid}/interface/#{@uuid}")
16
+ true
17
+ end
18
+
19
+ private
20
+
21
+ def after_initialize
22
+ @network = Network.new(@network) if @network
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,11 @@
1
+ module Tiktalik
2
+ module Computing
3
+
4
+ autoload :Instance, "#{ROOT}/tiktalik/computing/instance"
5
+ autoload :Network, "#{ROOT}/tiktalik/computing/network"
6
+ autoload :Operation, "#{ROOT}/tiktalik/computing/operation"
7
+ autoload :VPSImage, "#{ROOT}/tiktalik/computing/vpsimage"
8
+ autoload :VPSNetInterface, "#{ROOT}/tiktalik/computing/vpsnetinterface"
9
+
10
+ end
11
+ end
@@ -0,0 +1,56 @@
1
+ module Tiktalik
2
+ class Error < RuntimeError
3
+
4
+ class BadRequest < Tiktalik::Error
5
+ def status; 400; end
6
+ end
7
+
8
+ class Unauthorized < Tiktalik::Error
9
+ def status; 401; end
10
+ end
11
+
12
+ class PaymentRequired < Tiktalik::Error
13
+ def status; 402; end
14
+ end
15
+
16
+ class Forbidden < Tiktalik::Error
17
+ def status; 403; end
18
+ end
19
+
20
+ class NotFound < Tiktalik::Error
21
+ def status; 404; end
22
+ end
23
+
24
+ class NotAllowed < Tiktalik::Error
25
+ def status; 405; end
26
+ end
27
+
28
+ class Conflict < Tiktalik::Error
29
+ def status; 409; end
30
+ end
31
+
32
+ class ServerError < Tiktalik::Error
33
+ def status; 500; end
34
+ end
35
+
36
+ class UnknownStatus < Tiktalik::Error
37
+ def status; 500; end
38
+ end
39
+
40
+ STATUSES = {
41
+ 400 => BadRequest,
42
+ 401 => Unauthorized,
43
+ 402 => PaymentRequired,
44
+ 403 => Forbidden,
45
+ 404 => NotFound,
46
+ 405 => NotAllowed,
47
+ 409 => Conflict,
48
+ 500 => ServerError
49
+ }
50
+
51
+ def self.find_by_status(status)
52
+ STATUSES[status.to_i] || UnknownStatus
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,73 @@
1
+ require 'faraday'
2
+ require 'digest/hmac'
3
+ require 'base64'
4
+ require 'uri'
5
+ require 'multi_json'
6
+
7
+ # Base class for all objects returned by the API.
8
+ module Tiktalik
9
+ class Object
10
+
11
+ def initialize(json)
12
+ json.each do |key, value|
13
+ instance_variable_set("@#{key}", value)
14
+ end
15
+
16
+ after_initialize
17
+ end
18
+
19
+ private
20
+
21
+ def self.adapter
22
+ @@adapter ||= Faraday.new(:url => Tiktalik.base_url)
23
+ end
24
+
25
+ def self.request(method, path, params = {})
26
+ raise ArgumentError, "Set Tiktalik.api_key and Tiktalik.api_secret_key first" unless Tiktalik.api_key && Tiktalik.api_secret_key
27
+ date = Time.now.utc.strftime("%a, %d %b %Y %X GMT")
28
+ url = Tiktalik.base_path + path
29
+ url += "?" + URI.encode_www_form(params) unless params.nil? || params.empty? || method != :get
30
+ result = adapter.send(method) do |req|
31
+ req.url url
32
+ unless params.nil? || params.empty? || method == :get
33
+ req.body = URI.encode_www_form(params)
34
+ req.headers['content-md5'] = Digest::MD5.hexdigest(req.body)
35
+ end
36
+ req.headers['content-type'] = 'application/x-www-form-urlencoded'
37
+ req.headers['date'] = date
38
+ req.headers['Authorization'] = "TKAuth #{Tiktalik.api_key}:#{auth_key(method, url, req.headers)}"
39
+ end
40
+
41
+ raise_error(result.status, result.body) unless result.status == 200
42
+
43
+ MultiJson.load(result.body) rescue ""
44
+ end
45
+
46
+ def self.auth_key(method, url, headers)
47
+ string_to_sign = [method.to_s.upcase, headers['content-md5'], headers['content-type'], headers['date'], url].join("\n")
48
+ Base64.encode64(Digest::HMAC.digest(string_to_sign, Base64.decode64(Tiktalik.api_secret_key), Digest::SHA1)).strip
49
+ end
50
+
51
+ def self.raise_error(status, message = "")
52
+ message = "401 Not Authorized" if status == 401 # Bug in Tiktalik - return HTML instead of JSON
53
+ raise Error.find_by_status(status), message
54
+ end
55
+
56
+ def self.require_params(params, *require_list)
57
+ missing = require_list.sort - params.keys.sort
58
+ raise ArgumentError, "Missing attributes: #{missing}" unless missing.empty?
59
+ end
60
+
61
+ def after_initialize
62
+ end
63
+
64
+ def request(*args)
65
+ self.class.request(*args)
66
+ end
67
+
68
+ def require_params(*args)
69
+ self.class.require_params(*args)
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,3 @@
1
+ module Tiktalik
2
+ VERSION = "1.0.1"
3
+ end
data/lib/tiktalik.rb ADDED
@@ -0,0 +1,19 @@
1
+ module Tiktalik
2
+
3
+ ROOT = File.expand_path(File.dirname(__FILE__))
4
+
5
+ autoload :Computing, "#{ROOT}/tiktalik/computing"
6
+ autoload :Error, "#{ROOT}/tiktalik/error"
7
+ autoload :Object, "#{ROOT}/tiktalik/object"
8
+ autoload :VERSION, "#{ROOT}/tiktalik/version"
9
+
10
+ def self.base_url; 'https://www.tiktalik.com'; end
11
+ def self.base_path; '/api/v1'; end
12
+
13
+ def self.api_key; @api_key || ENV['API_KEY']; end
14
+ def self.api_key=(val); @api_key = val; end
15
+
16
+ def self.api_secret_key; @api_secret_key || ENV['API_SECRET_KEY']; end
17
+ def self.api_secret_key=(val); @api_secret_key = val; end
18
+
19
+ end
@@ -0,0 +1,255 @@
1
+ require 'spec_helper'
2
+
3
+ describe Tiktalik::Computing::Instance do
4
+
5
+ context ".all" do
6
+ let(:url) { "/api/v1/computing/instance" }
7
+ let(:method) { :get }
8
+ let(:request) { Tiktalik::Computing::Instance.method(:all) }
9
+
10
+ it "should return empty array if no instances found" do
11
+ $faraday_stubs.send(method, url) { [ 200, {}, '[]' ] }
12
+ results = request.call
13
+ results.class.should eql(Array)
14
+ results.size.should eql(0)
15
+ end
16
+
17
+ it "should return array with instances if some instances found" do
18
+ $faraday_stubs.send(method, url) { [ 200, {}, '[{},{}]' ] }
19
+ results = request.call
20
+ results.class.should eql(Array)
21
+ results.size.should eql(2)
22
+ results.each do |result|
23
+ result.class.should eql(Tiktalik::Computing::Instance)
24
+ end
25
+ end
26
+
27
+ it "should accept 'actions' parameter" do
28
+ $faraday_stubs.send(method, url + '?actions=true') { [ 200, {}, '[{},{}]' ] }
29
+ results = request.call(:actions => true)
30
+ results.class.should eql(Array)
31
+ results.size.should eql(2)
32
+ $faraday_stubs.verify_stubbed_calls
33
+ end
34
+
35
+ it "should accept 'vpsimage' parameter" do
36
+ $faraday_stubs.send(method, url + '?vpsimage=true') { [ 200, {}, '[{},{}]' ] }
37
+ results = request.call(:vpsimage => true)
38
+ results.class.should eql(Array)
39
+ results.size.should eql(2)
40
+ $faraday_stubs.verify_stubbed_calls
41
+ end
42
+
43
+ it "should accept 'cost' parameter" do
44
+ $faraday_stubs.send(method, url + '?cost=true') { [ 200, {}, '[{},{}]' ] }
45
+ results = request.call(:cost => true)
46
+ results.class.should eql(Array)
47
+ results.size.should eql(2)
48
+ $faraday_stubs.verify_stubbed_calls
49
+ end
50
+
51
+ it_should_behave_like 'support error 401'
52
+ it_should_behave_like 'support error 500'
53
+ end
54
+
55
+ context ".create" do
56
+ let(:url) { "/api/v1/computing/instance" }
57
+ let(:method) { :post }
58
+ let(:request) { Tiktalik::Computing::Instance.method(:create) }
59
+ let(:default_params) {{ :image_uuid => "123", :size => "0.25", :hostname => "test" }}
60
+
61
+ it_should_behave_like 'require parameters', [:image_uuid, :size, :hostname]
62
+
63
+ it "should create instance" do
64
+ $faraday_stubs.send(method, url) { [ 200, {}, '{}' ] }
65
+ result = request.call(default_params)
66
+ result.class.should eql(Tiktalik::Computing::Instance)
67
+ end
68
+
69
+ it "shuld wrap instance parameters" do
70
+ $faraday_stubs.send(method, url) { [ 200, {}, MultiJson.dump(INSTANCE_STUB) ] }
71
+ result = request.call(default_params)
72
+ result.class.should eql(Tiktalik::Computing::Instance)
73
+ result.uuid.should eql("71717dfb-3e86-487f-bcf0-01f6856d6bcd")
74
+ end
75
+
76
+ it_should_behave_like 'support error 400'
77
+ it_should_behave_like 'support error 401'
78
+ it_should_behave_like 'support error 402'
79
+ it_should_behave_like 'support error 403'
80
+ it_should_behave_like 'support error 500'
81
+ end
82
+
83
+ context ".find" do
84
+ let(:url) { "/api/v1/computing/instance/123" }
85
+ let(:method) { :get }
86
+ let(:request) { Tiktalik::Computing::Instance.method(:find) }
87
+ let(:default_params) {"123"}
88
+
89
+ it "should return instance" do
90
+ $faraday_stubs.send(method, url) { [ 200, {}, '{}' ] }
91
+ result = request.call(default_params)
92
+ result.class.should eql(Tiktalik::Computing::Instance)
93
+ end
94
+
95
+ it_should_behave_like 'support error 401'
96
+ it_should_behave_like 'support error 404'
97
+ end
98
+
99
+ context "instance" do
100
+ let(:subject) { Tiktalik::Computing::Instance.new(INSTANCE_STUB)}
101
+
102
+ its(:uuid) { should eql("71717dfb-3e86-487f-bcf0-01f6856d6bcd")}
103
+ its(:hostname) { should eql("test") }
104
+ its(:owner) { should eql("imanel") }
105
+ its(:vpsimage_uuid) { should eql("e18aee6c-9548-457e-9c20-7103d454969a") }
106
+ its(:state) { should eql(12) }
107
+ its(:running) { should eql(true) }
108
+ its(:default_password) { should eql("c933c94b8b") }
109
+ its(:service_name) { should eql("TC_UNIT_MICRO") }
110
+ its(:gross_cost_per_hour ) { should eql(0.03321) }
111
+
112
+ it "should have interfaces" do
113
+ subject.interfaces.class.should eql(Array)
114
+ subject.interfaces.size.should eql(1)
115
+ interface = subject.interfaces.first
116
+ interface.class.should eql(Tiktalik::Computing::VPSNetInterface)
117
+ interface.uuid.should eql("b5a097ee-a095-47b4-b7c7-4b11100559a7")
118
+ end
119
+
120
+ it "should have actions" do
121
+ subject.actions.class.should eql(Array)
122
+ subject.actions.size.should eql(1)
123
+ action = subject.actions.first
124
+ action.class.should eql(Tiktalik::Computing::Operation)
125
+ action.uuid.should eql("ad9a7aa3-dc61-4dde-92de-af335a635041")
126
+ end
127
+
128
+ it "should have vpsimage" do
129
+ subject.vpsimage.class.should eql(Tiktalik::Computing::VPSImage)
130
+ subject.vpsimage.uuid.should eql("e18aee6c-9548-457e-9c20-7103d454969a")
131
+ end
132
+
133
+ context "#destroy" do
134
+ let(:url) { "/api/v1/computing/instance/#{subject.uuid}" }
135
+ let(:method) { :delete }
136
+ let(:request) { subject.method(:destroy) }
137
+
138
+ it "should return true" do
139
+ $faraday_stubs.send(method, url) { [ 200, {}, '' ] }
140
+ request.call.should eql(true)
141
+ $faraday_stubs.verify_stubbed_calls
142
+ end
143
+
144
+ it_should_behave_like 'support error 401'
145
+ it_should_behave_like 'support error 403'
146
+ it_should_behave_like 'support error 500'
147
+ end
148
+
149
+ context "#build_interface" do
150
+ let(:url) { "/api/v1/computing/instance/#{subject.uuid}/interface" }
151
+ let(:method) { :post }
152
+ let(:request) { subject.method(:build_interface) }
153
+ let(:default_params) {{ :network_uuid => "123", :seq => 1 }}
154
+
155
+ it_should_behave_like 'require parameters', [:network_uuid, :seq]
156
+
157
+ it "should return interface" do
158
+ $faraday_stubs.send(method, url) { [ 200, {}, MultiJson.dump(VPSNETINTERFACE_STUB) ] }
159
+ result = request.call(default_params)
160
+ result.class.should eql(Tiktalik::Computing::VPSNetInterface)
161
+ result.uuid.should eql("b5a097ee-a095-47b4-b7c7-4b11100559a7")
162
+ end
163
+
164
+ it_should_behave_like 'support error 400'
165
+ it_should_behave_like 'support error 401'
166
+ it_should_behave_like 'support error 409'
167
+ it_should_behave_like 'support error 500'
168
+ end
169
+
170
+ context "#install" do
171
+ let(:url) { "/api/v1/computing/instance/#{subject.uuid}/install" }
172
+ let(:method) { :post }
173
+ let(:request) { subject.method(:install) }
174
+
175
+ it "should return true" do
176
+ $faraday_stubs.send(method, url) { [ 200, {}, '' ] }
177
+ request.call.should eql(true)
178
+ $faraday_stubs.verify_stubbed_calls
179
+ end
180
+
181
+ it_should_behave_like 'support error 401'
182
+ it_should_behave_like 'support error 403'
183
+ it_should_behave_like 'support error 409'
184
+ it_should_behave_like 'support error 500'
185
+ end
186
+
187
+ context "#start" do
188
+ let(:url) { "/api/v1/computing/instance/#{subject.uuid}/start" }
189
+ let(:method) { :post }
190
+ let(:request) { subject.method(:start) }
191
+
192
+ it "should return true" do
193
+ $faraday_stubs.send(method, url) { [ 200, {}, '' ] }
194
+ request.call.should eql(true)
195
+ $faraday_stubs.verify_stubbed_calls
196
+ end
197
+
198
+ it_should_behave_like 'support error 401'
199
+ it_should_behave_like 'support error 403'
200
+ it_should_behave_like 'support error 409'
201
+ it_should_behave_like 'support error 500'
202
+ end
203
+
204
+ context "#stop" do
205
+ let(:url) { "/api/v1/computing/instance/#{subject.uuid}/stop" }
206
+ let(:method) { :post }
207
+ let(:request) { subject.method(:stop) }
208
+
209
+ it "should return true" do
210
+ $faraday_stubs.send(method, url) { [ 200, {}, '' ] }
211
+ request.call.should eql(true)
212
+ $faraday_stubs.verify_stubbed_calls
213
+ end
214
+
215
+ it_should_behave_like 'support error 401'
216
+ it_should_behave_like 'support error 403'
217
+ it_should_behave_like 'support error 409'
218
+ it_should_behave_like 'support error 500'
219
+ end
220
+
221
+ context "#force_stop" do
222
+ let(:url) { "/api/v1/computing/instance/#{subject.uuid}/force_stop" }
223
+ let(:method) { :post }
224
+ let(:request) { subject.method(:force_stop) }
225
+
226
+ it "should return true" do
227
+ $faraday_stubs.send(method, url) { [ 200, {}, '' ] }
228
+ request.call.should eql(true)
229
+ $faraday_stubs.verify_stubbed_calls
230
+ end
231
+
232
+ it_should_behave_like 'support error 401'
233
+ it_should_behave_like 'support error 403'
234
+ it_should_behave_like 'support error 409'
235
+ it_should_behave_like 'support error 500'
236
+ end
237
+
238
+ context "#backup" do
239
+ let(:url) { "/api/v1/computing/instance/#{subject.uuid}/backup" }
240
+ let(:method) { :post }
241
+ let(:request) { subject.method(:backup) }
242
+
243
+ it "should return true" do
244
+ $faraday_stubs.send(method, url) { [ 200, {}, '' ] }
245
+ request.call.should eql(true)
246
+ $faraday_stubs.verify_stubbed_calls
247
+ end
248
+
249
+ it_should_behave_like 'support error 401'
250
+ it_should_behave_like 'support error 403'
251
+ it_should_behave_like 'support error 409'
252
+ it_should_behave_like 'support error 500'
253
+ end
254
+ end
255
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+ describe Tiktalik::Computing::Network do
4
+
5
+ context ".all" do
6
+ let(:url) { "/api/v1/computing/network" }
7
+ let(:method) { :get }
8
+ let(:request) { Tiktalik::Computing::Network.method(:all) }
9
+
10
+ it "should return empty array if no networks found" do
11
+ $faraday_stubs.send(method, url) { [ 200, {}, '[]' ] }
12
+ results = request.call
13
+ results.class.should eql(Array)
14
+ results.size.should eql(0)
15
+ end
16
+
17
+ it "should return array with networks if some networks found" do
18
+ $faraday_stubs.send(method, url) { [ 200, {}, '[{},{}]' ] }
19
+ results = request.call
20
+ results.class.should eql(Array)
21
+ results.size.should eql(2)
22
+ results.each do |result|
23
+ result.class.should eql(Tiktalik::Computing::Network)
24
+ end
25
+ end
26
+
27
+ it_should_behave_like 'support error 401'
28
+ it_should_behave_like 'support error 500'
29
+ end
30
+
31
+ context ".create" do
32
+ let(:url) { "/api/v1/computing/network" }
33
+ let(:method) { :post }
34
+ let(:request) { Tiktalik::Computing::Network.method(:create) }
35
+ let(:default_params) {{ :name => "test" }}
36
+
37
+ it_should_behave_like 'require parameters', [:name]
38
+
39
+ it "should create network" do
40
+ $faraday_stubs.send(method, url) { [ 200, {}, '{}' ] }
41
+ result = request.call(default_params)
42
+ result.class.should eql(Tiktalik::Computing::Network)
43
+ end
44
+
45
+ it "shuld wrap network parameters" do
46
+ $faraday_stubs.send(method, url) { [ 200, {}, MultiJson.dump(NETWORK_STUB) ] }
47
+ result = request.call(default_params)
48
+ result.class.should eql(Tiktalik::Computing::Network)
49
+ result.uuid.should eql("e92e60c2-2993-4a0c-b635-c5e2b2462c7a")
50
+ end
51
+
52
+ it_should_behave_like 'support error 400'
53
+ it_should_behave_like 'support error 401'
54
+ it_should_behave_like 'support error 500'
55
+ end
56
+
57
+ context ".find" do
58
+ let(:url) { "/api/v1/computing/network/123" }
59
+ let(:method) { :get }
60
+ let(:request) { Tiktalik::Computing::Network.method(:find) }
61
+ let(:default_params) {"123"}
62
+
63
+ it "should return network" do
64
+ $faraday_stubs.send(method, url) { [ 200, {}, '{}' ] }
65
+ result = request.call(default_params)
66
+ result.class.should eql(Tiktalik::Computing::Network)
67
+ end
68
+
69
+ it_should_behave_like 'support error 401'
70
+ it_should_behave_like 'support error 404'
71
+ end
72
+
73
+ context "instance" do
74
+ let(:subject) { Tiktalik::Computing::Network.new(NETWORK_STUB)}
75
+
76
+ its(:uuid) { should eql("e92e60c2-2993-4a0c-b635-c5e2b2462c7a") }
77
+ its(:name) { should eql("pub2") }
78
+ its(:net) { should eql("37.233.98.0/24") }
79
+ its(:owner) { should eql("system") }
80
+ its(:domainname) { should eql("p2.tiktalik.com") }
81
+ its(:public) { should eql(true) }
82
+ end
83
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Tiktalik::Computing::Operation do
4
+
5
+ context "instance" do
6
+ let(:subject) { Tiktalik::Computing::Operation.new(OPERATION_STUB)}
7
+
8
+ its(:uuid) { should eql("ad9a7aa3-dc61-4dde-92de-af335a635041") }
9
+ its(:start_time) { should eql(Time.parse("2013-05-29 10:38:31 +0200 (UTC)")) }
10
+ its(:end_time) { should eql(Time.parse("2013-05-29 10:39:13 +0200 (UTC)")) }
11
+ its(:description) { should eql("Create_Install: test") }
12
+ its(:progress) { should eql(100) }
13
+
14
+ end
15
+ end
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+
3
+ describe Tiktalik::Computing::VPSImage do
4
+
5
+ context ".all" do
6
+ let(:url) { "/api/v1/computing/image" }
7
+ let(:method) { :get }
8
+ let(:request) { Tiktalik::Computing::VPSImage.method(:all) }
9
+
10
+ it "should return empty array if no images found" do
11
+ $faraday_stubs.send(method, url) { [ 200, {}, '[]' ] }
12
+ results = request.call
13
+ results.class.should eql(Array)
14
+ results.size.should eql(0)
15
+ end
16
+
17
+ it "should return array with images if some images found" do
18
+ $faraday_stubs.send(method, url) { [ 200, {}, '[{},{}]' ] }
19
+ results = request.call
20
+ results.class.should eql(Array)
21
+ results.size.should eql(2)
22
+ results.each do |result|
23
+ result.class.should eql(Tiktalik::Computing::VPSImage)
24
+ end
25
+ end
26
+
27
+ it_should_behave_like 'support error 401'
28
+ it_should_behave_like 'support error 500'
29
+ end
30
+
31
+ context ".find" do
32
+ let(:url) { "/api/v1/computing/image/123" }
33
+ let(:method) { :get }
34
+ let(:request) { Tiktalik::Computing::VPSImage.method(:find) }
35
+ let(:default_params) {"123"}
36
+
37
+ it "should return image" do
38
+ $faraday_stubs.send(method, url) { [ 200, {}, '{}' ] }
39
+ result = request.call(default_params)
40
+ result.class.should eql(Tiktalik::Computing::VPSImage)
41
+ end
42
+
43
+ it_should_behave_like 'support error 401'
44
+ it_should_behave_like 'support error 404'
45
+ it_should_behave_like 'support error 500'
46
+ end
47
+
48
+ context "instance" do
49
+ let(:subject) { Tiktalik::Computing::VPSImage.new(VPSIMAGE_STUB)}
50
+
51
+ its(:uuid) { should eql("e18aee6c-9548-457e-9c20-7103d454969a") }
52
+ its(:name) { should eql("Centos 6.4 64-bit") }
53
+ its(:owner) { should eql("system") }
54
+ its(:type) { should eql("image") }
55
+ its(:is_public) { should eql(true) }
56
+ its(:description) { should eql("Some description") }
57
+ its(:create_time) { should eql(Time.parse("2013-03-25 15:29:51 +0100 (UTC)")) }
58
+
59
+ context "#destroy" do
60
+ let(:url) { "/api/v1/computing/image/#{subject.uuid}" }
61
+ let(:method) { :delete }
62
+ let(:request) { subject.method(:destroy) }
63
+
64
+ it "should return true" do
65
+ $faraday_stubs.send(method, url) { [ 200, {}, '' ] }
66
+ request.call.should eql(true)
67
+ $faraday_stubs.verify_stubbed_calls
68
+ end
69
+
70
+ it_should_behave_like 'support error 401'
71
+ it_should_behave_like 'support error 404'
72
+ it_should_behave_like 'support error 500'
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe Tiktalik::Computing::VPSNetInterface do
4
+
5
+ context "instance" do
6
+ let(:subject) { Tiktalik::Computing::VPSNetInterface.new(VPSNETINTERFACE_STUB)}
7
+
8
+ its(:uuid) { should eql("b5a097ee-a095-47b4-b7c7-4b11100559a7") }
9
+ its(:mac) { should eql("e6:95:e5:4c:99:86") }
10
+ its(:ip) { should eql("37.233.98.178") }
11
+ its(:seq ) { should eql(0) }
12
+
13
+ it "should have network" do
14
+ subject.network.class.should eql(Tiktalik::Computing::Network)
15
+ subject.network.uuid.should eql("e92e60c2-2993-4a0c-b635-c5e2b2462c7a")
16
+ end
17
+
18
+ context "#destroy" do
19
+ let(:url) { "/api/v1/computing/instance/#{INSTANCE_STUB["uuid"]}/interface/#{subject.uuid}" }
20
+ let(:method) { :delete }
21
+ let(:request) { subject.method(:destroy) }
22
+
23
+ it "should return true" do
24
+ $faraday_stubs.send(method, url) { [ 200, {}, '' ] }
25
+ request.call.should eql(true)
26
+ $faraday_stubs.verify_stubbed_calls
27
+ end
28
+
29
+ it_should_behave_like 'support error 401'
30
+ it_should_behave_like 'support error 404'
31
+ it_should_behave_like 'support error 405'
32
+ it_should_behave_like 'support error 500'
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+ require 'timecop'
3
+ require 'time'
4
+
5
+ describe Tiktalik::Object do
6
+ before do
7
+ Timecop.freeze(Time.parse("Wed, 29 May 2013 10:21:20 GMT" ))
8
+ end
9
+
10
+ after do
11
+ Timecop.return
12
+ end
13
+
14
+ context ".request" do
15
+ it "should have valid content type header set" do
16
+ $faraday_stubs.get("/api/v1/test", { "content-type" => 'application/x-www-form-urlencoded' }) { [200, {}, '']}
17
+ Tiktalik::Object.send(:request, :get, "/test")
18
+ $faraday_stubs.verify_stubbed_calls
19
+ end
20
+
21
+ it "should have valid date header set" do
22
+ $faraday_stubs.get("/api/v1/test", { "date" => "Wed, 29 May 2013 10:21:20 GMT" }) { [200, {}, '']}
23
+ Tiktalik::Object.send(:request, :get, "/test")
24
+ $faraday_stubs.verify_stubbed_calls
25
+ end
26
+
27
+ it "should have valid authorization header set" do
28
+ $faraday_stubs.get("/api/v1/test", { "Authorization" => "TKAuth API_KEY:is1EXmnDaRYNouQSHu5Wu36ZYg8=" }) { [200, {}, '']}
29
+ Tiktalik::Object.send(:request, :get, "/test")
30
+ $faraday_stubs.verify_stubbed_calls
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ require 'rspec'
2
+ require 'tiktalik'
3
+
4
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
5
+
6
+ RSpec.configure do |config|
7
+ config.before(:suite) do
8
+ # Everything is stubbed so we just need to set it to constant
9
+ Tiktalik.api_key = "API_KEY"
10
+ Tiktalik.api_secret_key = "API_SECRET_KEY"
11
+
12
+ # Stub all requests
13
+ require 'faraday/adapter/test'
14
+ $faraday_stubs = Faraday::Adapter::Test::Stubs.new
15
+ Tiktalik::Object.adapter.adapter :test, $faraday_stubs
16
+ end
17
+
18
+ config.before(:each) do
19
+ # Remove previously used stubs
20
+ $faraday_stubs.instance_variable_set("@stack", {})
21
+ $faraday_stubs.instance_variable_set("@consumed", {})
22
+ end
23
+ end
@@ -0,0 +1,63 @@
1
+ def expect_raise(error, message)
2
+ if defined?(default_params)
3
+ expect{ request.call(default_params) }.to raise_error(error, message)
4
+ else
5
+ expect{ request.call }.to raise_error(error, message)
6
+ end
7
+ end
8
+
9
+ shared_examples_for 'support error 400' do
10
+ it "should raise BadRequest error" do
11
+ $faraday_stubs.send(method, url) { [ 400, {}, '400 Bad Request' ] }
12
+ expect_raise(Tiktalik::Error::BadRequest, '400 Bad Request')
13
+ end
14
+ end
15
+
16
+ shared_examples_for 'support error 401' do
17
+ it "should raise Unauthorized error" do
18
+ $faraday_stubs.send(method, url) { [ 401, {}, '401 Not Authorized' ] }
19
+ expect_raise(Tiktalik::Error::Unauthorized, '401 Not Authorized')
20
+ end
21
+ end
22
+
23
+ shared_examples_for 'support error 402' do
24
+ it "should raise PaymentRequired error" do
25
+ $faraday_stubs.send(method, url) { [ 402, {}, '402 Payment Required' ] }
26
+ expect_raise(Tiktalik::Error::PaymentRequired, '402 Payment Required')
27
+ end
28
+ end
29
+
30
+ shared_examples_for 'support error 403' do
31
+ it "should raise Forbidden error" do
32
+ $faraday_stubs.send(method, url) { [ 403, {}, '403 Forbidden' ] }
33
+ expect_raise(Tiktalik::Error::Forbidden, '403 Forbidden')
34
+ end
35
+ end
36
+
37
+ shared_examples_for 'support error 404' do
38
+ it "should raise NotFound error" do
39
+ $faraday_stubs.send(method, url) { [ 404, {}, '404 Not Found' ] }
40
+ expect_raise(Tiktalik::Error::NotFound, '404 Not Found')
41
+ end
42
+ end
43
+
44
+ shared_examples_for 'support error 405' do
45
+ it "should raise NotAllowed error" do
46
+ $faraday_stubs.send(method, url) { [ 405, {}, '405 Not Allowed' ] }
47
+ expect_raise(Tiktalik::Error::NotAllowed, '405 Not Allowed')
48
+ end
49
+ end
50
+
51
+ shared_examples_for 'support error 409' do
52
+ it "should raise Conflict error" do
53
+ $faraday_stubs.send(method, url) { [ 409, {}, '409 Conflict' ] }
54
+ expect_raise(Tiktalik::Error::Conflict, '409 Conflict')
55
+ end
56
+ end
57
+
58
+ shared_examples_for 'support error 500' do
59
+ it "should raise ServerError error" do
60
+ $faraday_stubs.send(method, url) { [ 500, {}, '500 Server Error' ] }
61
+ expect_raise(Tiktalik::Error::ServerError, '500 Server Error')
62
+ end
63
+ end
@@ -0,0 +1,60 @@
1
+ NETWORK_STUB = {
2
+ "uuid"=>"e92e60c2-2993-4a0c-b635-c5e2b2462c7a",
3
+ "domainname"=>"p2.tiktalik.com",
4
+ "owner"=>"system",
5
+ "net"=>"37.233.98.0/24",
6
+ "public"=>true,
7
+ "name"=>"pub2"
8
+ }
9
+
10
+ OPERATION_STUB = {
11
+ "code"=>3,
12
+ "add_source"=>"imanel",
13
+ "end_time"=>"2013-05-29 10:39:13 +0200 (UTC)",
14
+ "uuid"=>"ad9a7aa3-dc61-4dde-92de-af335a635041",
15
+ "progress"=>100,
16
+ "end_code"=>0,
17
+ "start_time"=>"2013-05-29 10:38:31 +0200 (UTC)",
18
+ "description"=>"Create_Install: test",
19
+ "end_desc"=>"ok",
20
+ "add_time"=>"2013-05-29 10:38:30 +0200 (UTC)"
21
+ }
22
+
23
+ VPSIMAGE_STUB = {
24
+ "source_vps_size_name"=>nil,
25
+ "create_time"=>"2013-03-25 15:29:51 +0100 (UTC)",
26
+ "uuid"=>"e18aee6c-9548-457e-9c20-7103d454969a",
27
+ "source_vps_size_disk"=>nil,
28
+ "owner"=>"system",
29
+ "is_public"=>true,
30
+ "description"=>"Some description",
31
+ "type"=>"image",
32
+ "source_vps_size"=>nil,
33
+ "name"=>"Centos 6.4 64-bit"
34
+ }
35
+
36
+ VPSNETINTERFACE_STUB = {
37
+ "ip"=>"37.233.98.178",
38
+ "mac"=>"e6:95:e5:4c:99:86",
39
+ "uuid"=>"b5a097ee-a095-47b4-b7c7-4b11100559a7",
40
+ "seq"=>0,
41
+ "network"=>NETWORK_STUB,
42
+ "instance_uuid"=>"71717dfb-3e86-487f-bcf0-01f6856d6bcd"
43
+ }
44
+
45
+ INSTANCE_STUB = {
46
+ "actions_pending_count"=>0,
47
+ "service_name"=>"TC_UNIT_MICRO",
48
+ "interfaces"=>[VPSNETINTERFACE_STUB],
49
+ "actions"=>[OPERATION_STUB],
50
+ "running"=>true,
51
+ "vpsimage"=>VPSIMAGE_STUB,
52
+ "owner"=>"imanel",
53
+ "size"=>-2,
54
+ "uuid"=>"71717dfb-3e86-487f-bcf0-01f6856d6bcd",
55
+ "hostname"=>"test",
56
+ "state"=>12,
57
+ "gross_cost_per_hour"=>0.03321,
58
+ "default_password"=>"c933c94b8b",
59
+ "vpsimage_uuid"=>"e18aee6c-9548-457e-9c20-7103d454969a"
60
+ }
@@ -0,0 +1,8 @@
1
+ shared_examples_for 'require parameters' do |parameters|
2
+ parameters.each do |parameter|
3
+ it "should raise ArgumentError if #{parameter} is not provided" do
4
+ default_params.delete(parameter)
5
+ expect{ request.call(default_params) }.to raise_error(ArgumentError, "Missing attributes: [:#{parameter}]")
6
+ end
7
+ end
8
+ end
data/tiktalik.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "tiktalik/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "tiktalik"
7
+ s.version = Tiktalik::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Bernard Potocki"]
10
+ s.email = ["bernard.potocki@imanel.org"]
11
+ s.homepage = "http://github.com/tiktalik-cloud/tiktalik-ruby"
12
+ s.summary = %q{Tiktalik.com Ruby API library}
13
+ s.description = %q{Tiktalik.com Ruby API library}
14
+
15
+ s.add_dependency 'faraday', '~> 0.9.0.rc5'
16
+ s.add_dependency 'multi_json', '~> 1.7.9'
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tiktalik
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Bernard Potocki
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-08-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.9.0.rc5
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.9.0.rc5
27
+ - !ruby/object:Gem::Dependency
28
+ name: multi_json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 1.7.9
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 1.7.9
41
+ description: Tiktalik.com Ruby API library
42
+ email:
43
+ - bernard.potocki@imanel.org
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gitignore
49
+ - .travis.yml
50
+ - Gemfile
51
+ - README.md
52
+ - Rakefile
53
+ - lib/tiktalik.rb
54
+ - lib/tiktalik/computing.rb
55
+ - lib/tiktalik/computing/instance.rb
56
+ - lib/tiktalik/computing/network.rb
57
+ - lib/tiktalik/computing/operation.rb
58
+ - lib/tiktalik/computing/vpsimage.rb
59
+ - lib/tiktalik/computing/vpsnetinterface.rb
60
+ - lib/tiktalik/error.rb
61
+ - lib/tiktalik/object.rb
62
+ - lib/tiktalik/version.rb
63
+ - spec/computing/instance_spec.rb
64
+ - spec/computing/network_spec.rb
65
+ - spec/computing/operation_spec.rb
66
+ - spec/computing/vpsimage_spec.rb
67
+ - spec/computing/vpsnetinterface_spec.rb
68
+ - spec/object_spec.rb
69
+ - spec/spec_helper.rb
70
+ - spec/support/error_requests.rb
71
+ - spec/support/stubs.rb
72
+ - spec/support/validations.rb
73
+ - tiktalik.gemspec
74
+ homepage: http://github.com/tiktalik-cloud/tiktalik-ruby
75
+ licenses: []
76
+ metadata: {}
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 2.0.7
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: Tiktalik.com Ruby API library
97
+ test_files:
98
+ - spec/computing/instance_spec.rb
99
+ - spec/computing/network_spec.rb
100
+ - spec/computing/operation_spec.rb
101
+ - spec/computing/vpsimage_spec.rb
102
+ - spec/computing/vpsnetinterface_spec.rb
103
+ - spec/object_spec.rb
104
+ - spec/spec_helper.rb
105
+ - spec/support/error_requests.rb
106
+ - spec/support/stubs.rb
107
+ - spec/support/validations.rb