tiktalik 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.travis.yml +12 -0
- data/Gemfile +8 -0
- data/README.md +50 -0
- data/Rakefile +11 -0
- data/lib/tiktalik/computing/instance.rb +118 -0
- data/lib/tiktalik/computing/network.rb +42 -0
- data/lib/tiktalik/computing/operation.rb +22 -0
- data/lib/tiktalik/computing/vpsimage.rb +42 -0
- data/lib/tiktalik/computing/vpsnetinterface.rb +27 -0
- data/lib/tiktalik/computing.rb +11 -0
- data/lib/tiktalik/error.rb +56 -0
- data/lib/tiktalik/object.rb +73 -0
- data/lib/tiktalik/version.rb +3 -0
- data/lib/tiktalik.rb +19 -0
- data/spec/computing/instance_spec.rb +255 -0
- data/spec/computing/network_spec.rb +83 -0
- data/spec/computing/operation_spec.rb +15 -0
- data/spec/computing/vpsimage_spec.rb +76 -0
- data/spec/computing/vpsnetinterface_spec.rb +35 -0
- data/spec/object_spec.rb +33 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/support/error_requests.rb +63 -0
- data/spec/support/stubs.rb +60 -0
- data/spec/support/validations.rb +8 -0
- data/tiktalik.gemspec +22 -0
- metadata +107 -0
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
data/.travis.yml
ADDED
data/Gemfile
ADDED
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,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
|
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
|
data/spec/object_spec.rb
ADDED
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|