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 +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
|