tiktalik 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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