atlantic_net 0.1.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 +4 -0
- data/.travis.yml +3 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +30 -0
- data/Rakefile +6 -0
- data/atlantic_net.gemspec +27 -0
- data/lib/atlantic_net.rb +260 -0
- data/spec/atlantic_net_spec.rb +608 -0
- data/spec/spec_helper.rb +11 -0
- metadata +210 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 299bbd01dc49308dc29dcd96726cb87d285ea780
|
4
|
+
data.tar.gz: 4a88ca4ab658e36d2304751256add890efb9aff5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a71669c2dcb9c443e6a82dd7a2272b040b80bea41e449ce399caee070ccd86debe8a2ef2cadbfdc6924a9cfb7d2499d8de0c79c968ddb89964dbbe02c33ab5e4
|
7
|
+
data.tar.gz: 13edd8a8cb2ce77f949d6fbea6ed3b0e7fb5c3e6f1b711cc586d9d12859879cf4dd4879c5f69f6c7ca48eb72109529bc406cae5bd51915212f6f6be35c07a4ae
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2016 Jamie Starke
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# atlantic_net
|
2
|
+
|
3
|
+
[](https://travis-ci.org/jrstarke/atlantic_net)
|
4
|
+
[](https://coveralls.io/r/jrstarke/atlantic_net)
|
5
|
+
|
6
|
+
A lightweight ruby interface for interacting with the Atlantic.net API.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add atlantic_net to your Gemfile:
|
11
|
+
|
12
|
+
``` ruby
|
13
|
+
gem "atlantic_net"
|
14
|
+
```
|
15
|
+
|
16
|
+
## Usage
|
17
|
+
|
18
|
+
``` ruby
|
19
|
+
# Require the atlantic_net library
|
20
|
+
require 'atlantic_net'
|
21
|
+
|
22
|
+
# Instantiate the client with your access key and private key
|
23
|
+
client = AtlanticNet.new(access_key, private_key)
|
24
|
+
|
25
|
+
# List instances
|
26
|
+
instances = client.list_instances
|
27
|
+
|
28
|
+
# Reboot an instance
|
29
|
+
subject.reboot_instance(instances.first["InstanceId"])
|
30
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Gem::Specification.new do |spec|
|
2
|
+
spec.name = "atlantic_net"
|
3
|
+
spec.version = "0.1.1"
|
4
|
+
spec.authors = ["Jamie Starke"]
|
5
|
+
spec.email = ["git@jamiestarke.com"]
|
6
|
+
spec.description = "A Ruby wrapper of the Atlantic.net API"
|
7
|
+
spec.summary = "A Ruby wrapper of the Atlantic.net API"
|
8
|
+
spec.homepage = "http://github.com/jrstarke/atlantic_net"
|
9
|
+
spec.license = "MIT"
|
10
|
+
|
11
|
+
spec.files = `git ls-files`.split($/)
|
12
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
13
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
14
|
+
spec.require_paths = ["lib"]
|
15
|
+
|
16
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
17
|
+
spec.add_development_dependency "rake"
|
18
|
+
spec.add_development_dependency "rack-test"
|
19
|
+
spec.add_development_dependency "rspec", ">= 3.0.0"
|
20
|
+
spec.add_development_dependency "rspec-given"
|
21
|
+
spec.add_development_dependency "simplecov"
|
22
|
+
spec.add_development_dependency "coveralls"
|
23
|
+
spec.add_development_dependency "uuidtools"
|
24
|
+
spec.add_development_dependency "webmock"
|
25
|
+
spec.add_development_dependency "pry"
|
26
|
+
spec.add_development_dependency 'pry-nav'
|
27
|
+
end
|
data/lib/atlantic_net.rb
ADDED
@@ -0,0 +1,260 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'openssl'
|
3
|
+
require 'securerandom'
|
4
|
+
require 'pry'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
class AtlanticNetException < StandardError
|
8
|
+
attr_reader :atlantic_net_instance, :api_response
|
9
|
+
|
10
|
+
def initialize(instance, response, message)
|
11
|
+
super(message)
|
12
|
+
@atlantic_net_instance = instance
|
13
|
+
@api_response = response
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class AtlanticNet
|
18
|
+
|
19
|
+
VERSION = "2010-12-30"
|
20
|
+
FORMAT = "json"
|
21
|
+
|
22
|
+
class HttpTransport
|
23
|
+
|
24
|
+
API_URI = "https://cloudapi.atlantic.net"
|
25
|
+
|
26
|
+
# Sends the request to the API endpoint
|
27
|
+
#
|
28
|
+
# @param [Hash] data The Data to pass with the request
|
29
|
+
#
|
30
|
+
def send_request (data)
|
31
|
+
uri = URI.parse(API_URI)
|
32
|
+
uri.query = URI.encode_www_form(data)
|
33
|
+
|
34
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
35
|
+
http.use_ssl = true
|
36
|
+
|
37
|
+
response = http.get(uri.request_uri)
|
38
|
+
|
39
|
+
unless response.code.to_i == 200
|
40
|
+
fail AtlanticNetException.new(nil, {}, "The Atlantic.net api endpoint was unexpectedly unavailable. The HTTP Status code was #{response.code}")
|
41
|
+
end
|
42
|
+
|
43
|
+
JSON.parse(response.body)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# @param [String] access_key The Access Key for your Account.
|
48
|
+
# This is the "API Public Key" from the Account Settings page.
|
49
|
+
#
|
50
|
+
# @param [String] private_key The Private Key for your Account.
|
51
|
+
# This is the "API Private Key" from the Account Settings page.
|
52
|
+
#
|
53
|
+
def initialize(access_key, private_key, options = {})
|
54
|
+
@access_key = access_key
|
55
|
+
@private_key = private_key
|
56
|
+
@transport = transport_from_options(options)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Generates a Base64 encoded Sha256 HMAC given a timestamp and a request_id
|
60
|
+
#
|
61
|
+
# @param [String,Int] timestamp The timestamp of the requesting call.
|
62
|
+
# This should be the time the the request was originally made.
|
63
|
+
#
|
64
|
+
# @param [String] request_id The UUID representing the request.
|
65
|
+
# This should be unique for each request.
|
66
|
+
#
|
67
|
+
# @return [String] A Base64 encoded HMAC of the timestamp and request_id
|
68
|
+
#
|
69
|
+
def signature(timestamp, request_id)
|
70
|
+
string_to_sign = "#{timestamp}#{request_id}"
|
71
|
+
|
72
|
+
digest = OpenSSL::Digest.new('sha256')
|
73
|
+
Base64.encode64(OpenSSL::HMAC.digest(digest, @private_key, string_to_sign)).strip()
|
74
|
+
end
|
75
|
+
|
76
|
+
# Retrieve the list of currently active cloud servers.
|
77
|
+
#
|
78
|
+
# @return [Array<Hash>] The list of servers
|
79
|
+
#
|
80
|
+
def list_instances
|
81
|
+
response = api_call('list-instances')
|
82
|
+
response['list-instancesresponse']['instancesSet'].values
|
83
|
+
end
|
84
|
+
|
85
|
+
# Restart a specific cloud server.
|
86
|
+
#
|
87
|
+
# @param [String] instance_id The instance ID of the server you want to reboot.
|
88
|
+
#
|
89
|
+
# @param [Hash] options The options to include with restart.
|
90
|
+
# @option options [String] :reboot_type (soft) Whether you want to perform a soft or hard reboot.
|
91
|
+
# soft is the equivalent of performing a graceful shutdown.
|
92
|
+
# hard is the equivalent of disconnecting the power and reconnecting it.
|
93
|
+
#
|
94
|
+
# @return [Hash] The return value of the request
|
95
|
+
#
|
96
|
+
def reboot_instance(instance_id, options={})
|
97
|
+
reboot_type = options[:reboot_type] || "soft"
|
98
|
+
response = api_call('reboot-instance', {instanceid: instance_id, reboottype: reboot_type})
|
99
|
+
response["reboot-instanceresponse"]["return"]
|
100
|
+
end
|
101
|
+
|
102
|
+
# Describe a specific cloud server.
|
103
|
+
#
|
104
|
+
# @param [String] instance_id The instance ID of the server you want to describe.
|
105
|
+
#
|
106
|
+
# @return [Hash] The hash of the instance
|
107
|
+
#
|
108
|
+
def describe_instance(instance_id)
|
109
|
+
response = api_call('describe-instance', {instanceid: instance_id})
|
110
|
+
response["describe-instanceresponse"]["instanceSet"]["item"]
|
111
|
+
end
|
112
|
+
|
113
|
+
# Terminate a specific cloud server.
|
114
|
+
#
|
115
|
+
# @param [String] instance_id The instance ID of the server you want to terminate.
|
116
|
+
#
|
117
|
+
# @return [Hash] The termination response result.
|
118
|
+
#
|
119
|
+
def terminate_instance(instance_id)
|
120
|
+
response = api_call('terminate-instance', {instanceid: instance_id})
|
121
|
+
response["terminate-instanceresponse"]["instancesSet"]["item"]
|
122
|
+
end
|
123
|
+
|
124
|
+
# Run a cloud server with the provided configuration options.
|
125
|
+
#
|
126
|
+
# @param [String] server_name The name/description that will be used for the instance
|
127
|
+
#
|
128
|
+
# @param [String] plan_name The plan that should be used for this instance
|
129
|
+
#
|
130
|
+
# @param [String] vm_location The data center location you want this instance launched
|
131
|
+
#
|
132
|
+
# @param [Hash] args A hash of the options
|
133
|
+
# @option options [String] :image_id The VM image to use for this instance. This or :clone_image are required.
|
134
|
+
# @option options [String] :clone_image The server to clone for this instance. This or :image_id are required.
|
135
|
+
# @option options [Boolean] :enable_backup Whether backups should be enabled for this instance.
|
136
|
+
# @option options [Int] :server_quantity How many instances of this server should be launched.
|
137
|
+
# @option options [String] :key_id The ID of the key to deploy for accessing this server.
|
138
|
+
#
|
139
|
+
# @return [Hash] The run instance result
|
140
|
+
#
|
141
|
+
def run_instance(server_name, plan_name, vm_location, options={})
|
142
|
+
option_mapping = {
|
143
|
+
image_id: :imageid,
|
144
|
+
clone_image: :cloneimage,
|
145
|
+
enable_backup: :enablebackup,
|
146
|
+
server_quantity: :serverqty,
|
147
|
+
key_id: :key_id
|
148
|
+
}
|
149
|
+
|
150
|
+
request_options = {servername: server_name, planname: plan_name, vm_location: vm_location}
|
151
|
+
|
152
|
+
unless options.has_key? :image_id or options.has_key? :clone_image
|
153
|
+
fail ArgumentError.new("Missing argument: image_id or clone_image are required")
|
154
|
+
end
|
155
|
+
|
156
|
+
option_mapping.each do | key, value |
|
157
|
+
if options.has_key? key
|
158
|
+
request_options[value] = options[key]
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
response = api_call('run-instance', request_options)
|
163
|
+
response["run-instanceresponse"]["instancesSet"]["item"]
|
164
|
+
end
|
165
|
+
|
166
|
+
# Retrieve the description of all available cloud images or the description of a specific cloud image by providing the image id
|
167
|
+
#
|
168
|
+
# @param [Hash] options A hash of the options
|
169
|
+
# @option options [String] :image_id ID indicating the flavor and version number of the operating system image
|
170
|
+
#
|
171
|
+
# @return [Array<Hash>] A array of image descriptions
|
172
|
+
#
|
173
|
+
def describe_images(options={})
|
174
|
+
args = {}
|
175
|
+
|
176
|
+
if options.has_key? :image_id
|
177
|
+
response = api_call('describe-image', {imageid: options[:image_id]})
|
178
|
+
else
|
179
|
+
response = api_call('describe-image')
|
180
|
+
end
|
181
|
+
|
182
|
+
response["describe-imageresponse"]["imagesset"].values
|
183
|
+
end
|
184
|
+
|
185
|
+
# Retrieve a list of available cloud server plans, narrow the listing down optionally
|
186
|
+
# by server platform, or get information about just one specific plan
|
187
|
+
#
|
188
|
+
# @param [Hash] options A hash of the options
|
189
|
+
# @option options [String] plan_name The name of the plan to describe
|
190
|
+
# @option options [String] platform The platform to filter plans by (windows, linux)
|
191
|
+
#
|
192
|
+
# @return [Array<Hash>] An array of plan descriptions
|
193
|
+
#
|
194
|
+
def describe_plans(options={})
|
195
|
+
if options.empty?
|
196
|
+
response = api_call('describe-plan')
|
197
|
+
else
|
198
|
+
response = api_call('describe-plan',options)
|
199
|
+
end
|
200
|
+
|
201
|
+
response["describe-planresponse"]["plans"].values
|
202
|
+
end
|
203
|
+
|
204
|
+
# Retrieve the details of all SSH Keys associated with the account
|
205
|
+
#
|
206
|
+
# @return [Array<Hash>] An array of SSH keys
|
207
|
+
#
|
208
|
+
def list_ssh_keys
|
209
|
+
response = api_call('list-sshkeys')
|
210
|
+
response["list-sshkeysresponse"]["KeysSet"].values
|
211
|
+
end
|
212
|
+
|
213
|
+
|
214
|
+
protected
|
215
|
+
|
216
|
+
# Generate the next timestamp and request_id combination
|
217
|
+
#
|
218
|
+
# @return [Int, String] timestamp, request_id
|
219
|
+
#
|
220
|
+
def generate_request_id_tuple
|
221
|
+
timestamp = Time.now().to_i
|
222
|
+
request_uuid = SecureRandom.uuid
|
223
|
+
[timestamp, request_uuid]
|
224
|
+
end
|
225
|
+
|
226
|
+
# Performs the request and sends it off to the transport
|
227
|
+
#
|
228
|
+
# @param [String] action The API Action to perform.
|
229
|
+
#
|
230
|
+
# @param [Hash] args The arguments to pass with the request to the API.
|
231
|
+
#
|
232
|
+
def api_call(action, args = {})
|
233
|
+
timestamp, request_id = generate_request_id_tuple()
|
234
|
+
request_signature = signature(timestamp, request_id)
|
235
|
+
|
236
|
+
args = args.merge(
|
237
|
+
Version: VERSION,
|
238
|
+
ACSAccessKeyId: @access_key,
|
239
|
+
Format: FORMAT,
|
240
|
+
Timestamp: timestamp,
|
241
|
+
Rndguid: request_id,
|
242
|
+
Signature: request_signature,
|
243
|
+
Action: action
|
244
|
+
)
|
245
|
+
|
246
|
+
response = @transport.send_request(args)
|
247
|
+
if response.has_key? "error"
|
248
|
+
fail AtlanticNetException.new(self, response, response["error"]["message"])
|
249
|
+
end
|
250
|
+
|
251
|
+
response
|
252
|
+
end
|
253
|
+
|
254
|
+
private
|
255
|
+
|
256
|
+
def transport_from_options(options)
|
257
|
+
options[:transport] || AtlanticNet::HttpTransport.new
|
258
|
+
end
|
259
|
+
|
260
|
+
end
|
@@ -0,0 +1,608 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe AtlanticNet do
|
4
|
+
let(:subject) { AtlanticNet.new(access_key, private_key, options) }
|
5
|
+
|
6
|
+
let(:access_key) { "public_key" }
|
7
|
+
let(:private_key) { "secret" }
|
8
|
+
|
9
|
+
let(:options) { { transport: transport } }
|
10
|
+
let(:transport) { double(:transport, send_request: {}) }
|
11
|
+
|
12
|
+
let(:sample_timestamp) { "Mess" }
|
13
|
+
let(:sample_request_id) { "age" }
|
14
|
+
let(:sample_signature) { "qnR8UCqJggD55PohusaBNviGoOJ67HC6Btry4qXLVZc=" }
|
15
|
+
|
16
|
+
describe "#signature" do
|
17
|
+
it 'returns sample signature' do
|
18
|
+
signature = subject.signature(sample_timestamp,sample_request_id)
|
19
|
+
expect(signature).to eq sample_signature
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#list_instances" do
|
24
|
+
let(:sample_api_response) {
|
25
|
+
{
|
26
|
+
"Timestamp" => 1440018626,
|
27
|
+
"list-instancesresponse" => {
|
28
|
+
"instancesSet" => {
|
29
|
+
"1item" => {
|
30
|
+
"InstanceId" => "145607",
|
31
|
+
"cu_id" => "17",
|
32
|
+
"rate_per_hr" => "0.0341",
|
33
|
+
"vm_bandwidth" => "600",
|
34
|
+
"vm_cpu_req" => "1",
|
35
|
+
"vm_created_date" => "1438048503",
|
36
|
+
"vm_description" => "New",
|
37
|
+
"vm_disk_req" => "40",
|
38
|
+
"vm_image" => "CentOS-7.1-cPanel_64bit",
|
39
|
+
"vm_image_display_name" => "CentOS 6.5 64bit Server - cPanel/WHM",
|
40
|
+
"vm_ip_address" => "209.208.65.177",
|
41
|
+
"vm_name" => "17-145607",
|
42
|
+
"vm_network_req" => "1",
|
43
|
+
"vm_os_architecture" => "64",
|
44
|
+
"vm_plan_name" => "S",
|
45
|
+
"vm_ram_req" => "1024",
|
46
|
+
"vm_status" => "RUNNING"
|
47
|
+
},
|
48
|
+
"item" => {
|
49
|
+
"InstanceId" => "153979",
|
50
|
+
"cu_id" => "17",
|
51
|
+
"rate_per_hr" => "0.0547",
|
52
|
+
"vm_bandwidth" => "600",
|
53
|
+
"vm_cpu_req" => "2",
|
54
|
+
"vm_created_date" => "1440018294",
|
55
|
+
"vm_description" => "apitestserver",
|
56
|
+
"vm_disk_req" => "100",
|
57
|
+
"vm_image" => "ubuntu-14.04_64bit",
|
58
|
+
"vm_image_display_name" => "ubuntu-14.04_64bit",
|
59
|
+
"vm_ip_address" => "45.58.35.251",
|
60
|
+
"vm_name" => "17-153979",
|
61
|
+
"vm_network_req" => "1",
|
62
|
+
"vm_os_architecture" => "64",
|
63
|
+
"vm_plan_name" => "L",
|
64
|
+
"vm_ram_req" => "4096",
|
65
|
+
"vm_status" => "RUNNING"
|
66
|
+
}
|
67
|
+
},
|
68
|
+
"requestid" => "c2a1bc2a-4440-438a-bd28-74dbc10a4047"
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}
|
72
|
+
let(:expected_instances) {
|
73
|
+
[
|
74
|
+
{
|
75
|
+
"InstanceId" => "145607",
|
76
|
+
"cu_id" => "17",
|
77
|
+
"rate_per_hr" => "0.0341",
|
78
|
+
"vm_bandwidth" => "600",
|
79
|
+
"vm_cpu_req" => "1",
|
80
|
+
"vm_created_date" => "1438048503",
|
81
|
+
"vm_description" => "New",
|
82
|
+
"vm_disk_req" => "40",
|
83
|
+
"vm_image" => "CentOS-7.1-cPanel_64bit",
|
84
|
+
"vm_image_display_name" => "CentOS 6.5 64bit Server - cPanel/WHM",
|
85
|
+
"vm_ip_address" => "209.208.65.177",
|
86
|
+
"vm_name" => "17-145607",
|
87
|
+
"vm_network_req" => "1",
|
88
|
+
"vm_os_architecture" => "64",
|
89
|
+
"vm_plan_name" => "S",
|
90
|
+
"vm_ram_req" => "1024",
|
91
|
+
"vm_status" => "RUNNING"
|
92
|
+
},
|
93
|
+
{
|
94
|
+
"InstanceId" => "153979",
|
95
|
+
"cu_id" => "17",
|
96
|
+
"rate_per_hr" => "0.0547",
|
97
|
+
"vm_bandwidth" => "600",
|
98
|
+
"vm_cpu_req" => "2",
|
99
|
+
"vm_created_date" => "1440018294",
|
100
|
+
"vm_description" => "apitestserver",
|
101
|
+
"vm_disk_req" => "100",
|
102
|
+
"vm_image" => "ubuntu-14.04_64bit",
|
103
|
+
"vm_image_display_name" => "ubuntu-14.04_64bit",
|
104
|
+
"vm_ip_address" => "45.58.35.251",
|
105
|
+
"vm_name" => "17-153979",
|
106
|
+
"vm_network_req" => "1",
|
107
|
+
"vm_os_architecture" => "64",
|
108
|
+
"vm_plan_name" => "L",
|
109
|
+
"vm_ram_req" => "4096",
|
110
|
+
"vm_status" => "RUNNING"
|
111
|
+
}
|
112
|
+
]
|
113
|
+
}
|
114
|
+
|
115
|
+
# it 'calls api_call with list-instances api' do
|
116
|
+
# expect(subject).to receive(:api_call).with("list-instances").and_return(sample_api_response)
|
117
|
+
# subject.list_instances
|
118
|
+
# end
|
119
|
+
|
120
|
+
it 'calls api_call with list-instances and returns a list of instance hashes' do
|
121
|
+
allow(subject).to receive(:api_call).with("list-instances").and_return(sample_api_response)
|
122
|
+
instances = subject.list_instances
|
123
|
+
expect(instances).to eq expected_instances
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe '#reboot_instance' do
|
128
|
+
let(:instance_id) { "234" }
|
129
|
+
let(:sample_api_response) {
|
130
|
+
{
|
131
|
+
"Timestamp" => 1440171938,
|
132
|
+
"reboot-instanceresponse" => {
|
133
|
+
"requestid" => "6723430f-c416-46de-a03d-2d2ea38d3af7",
|
134
|
+
"return" => {
|
135
|
+
"Message" => "Successfully queued for reboot",
|
136
|
+
"value" => "true"
|
137
|
+
}
|
138
|
+
}
|
139
|
+
}
|
140
|
+
}
|
141
|
+
let(:expected_return) {
|
142
|
+
{
|
143
|
+
"Message" => "Successfully queued for reboot",
|
144
|
+
"value" => "true"
|
145
|
+
}
|
146
|
+
}
|
147
|
+
|
148
|
+
context "default options" do
|
149
|
+
let(:reboot_type) { "soft" }
|
150
|
+
|
151
|
+
it 'calls api_call with reboot-instance and instance_id' do
|
152
|
+
expect(subject).to receive(:api_call)
|
153
|
+
.with("reboot-instance", {instanceid: instance_id, reboottype: reboot_type})
|
154
|
+
.and_return(sample_api_response)
|
155
|
+
result = subject.reboot_instance(instance_id)
|
156
|
+
expect(result).to eq expected_return
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context "reboot_type override" do
|
161
|
+
let(:reboot_type) { "hard" }
|
162
|
+
|
163
|
+
it 'calls api_call with reboot-instance, instance_id and reboot_type' do
|
164
|
+
expect(subject).to receive(:api_call)
|
165
|
+
.with("reboot-instance", {instanceid: instance_id, reboottype: reboot_type})
|
166
|
+
.and_return(sample_api_response)
|
167
|
+
result = subject.reboot_instance(instance_id, reboot_type: reboot_type)
|
168
|
+
expect(result).to eq expected_return
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe "#describe_instance" do
|
174
|
+
let(:instance_id) { "234" }
|
175
|
+
let(:sample_api_response) {
|
176
|
+
{
|
177
|
+
"Timestamp" => 1440020019,
|
178
|
+
"describe-instanceresponse" => {
|
179
|
+
"instanceSet" => {
|
180
|
+
"item" => {
|
181
|
+
"InstanceId" => "153979",
|
182
|
+
"cloned_from" => "",
|
183
|
+
"cu_id" => "17",
|
184
|
+
"disallow_deletion" => "N",
|
185
|
+
"rate_per_hr" => "0.0547",
|
186
|
+
"removed" => "N",
|
187
|
+
"reprovisioning_processed_date" => nil,
|
188
|
+
"resetpwd_processed_date" => nil,
|
189
|
+
"vm_bandwidth" => "600",
|
190
|
+
"vm_cpu_req" => "2",
|
191
|
+
"vm_created_date" => "1440018294",
|
192
|
+
"vm_description" => "apitestserver",
|
193
|
+
"vm_disk_req" => "100",
|
194
|
+
"vm_id" => "153979",
|
195
|
+
"vm_image" => "ubuntu-14.04_64bit",
|
196
|
+
"vm_image_display_name" => "ubuntu-14.04_64bit",
|
197
|
+
"vm_ip_address" => "45.58.35.251",
|
198
|
+
"vm_ip_gateway" => "45.58.34.1",
|
199
|
+
"vm_ip_subnet" => "255.255.254.0",
|
200
|
+
"vm_network_req" => "1",
|
201
|
+
"vm_os_architecture" => "64",
|
202
|
+
"vm_plan_name" => "L",
|
203
|
+
"vm_ram_req" => "4096",
|
204
|
+
"vm_removed_date" => nil,
|
205
|
+
"vm_status" => "RUNNING",
|
206
|
+
"vm_username" => "root",
|
207
|
+
"vm_vnc_password" => "8$EOs$Rs",
|
208
|
+
"vnc_port" => "18248"
|
209
|
+
}
|
210
|
+
},
|
211
|
+
"requestid" => "3affbe87-ad45-41de-a1d2-29b522aa88b2"
|
212
|
+
}
|
213
|
+
}
|
214
|
+
}
|
215
|
+
let(:expected_instance) {
|
216
|
+
{
|
217
|
+
"InstanceId" => "153979",
|
218
|
+
"cloned_from" => "",
|
219
|
+
"cu_id" => "17",
|
220
|
+
"disallow_deletion" => "N",
|
221
|
+
"rate_per_hr" => "0.0547",
|
222
|
+
"removed" => "N",
|
223
|
+
"reprovisioning_processed_date" => nil,
|
224
|
+
"resetpwd_processed_date" => nil,
|
225
|
+
"vm_bandwidth" => "600",
|
226
|
+
"vm_cpu_req" => "2",
|
227
|
+
"vm_created_date" => "1440018294",
|
228
|
+
"vm_description" => "apitestserver",
|
229
|
+
"vm_disk_req" => "100",
|
230
|
+
"vm_id" => "153979",
|
231
|
+
"vm_image" => "ubuntu-14.04_64bit",
|
232
|
+
"vm_image_display_name" => "ubuntu-14.04_64bit",
|
233
|
+
"vm_ip_address" => "45.58.35.251",
|
234
|
+
"vm_ip_gateway" => "45.58.34.1",
|
235
|
+
"vm_ip_subnet" => "255.255.254.0",
|
236
|
+
"vm_network_req" => "1",
|
237
|
+
"vm_os_architecture" => "64",
|
238
|
+
"vm_plan_name" => "L",
|
239
|
+
"vm_ram_req" => "4096",
|
240
|
+
"vm_removed_date" => nil,
|
241
|
+
"vm_status" => "RUNNING",
|
242
|
+
"vm_username" => "root",
|
243
|
+
"vm_vnc_password" => "8$EOs$Rs",
|
244
|
+
"vnc_port" => "18248"
|
245
|
+
}
|
246
|
+
}
|
247
|
+
|
248
|
+
it 'calls api_call with describe-instance and returns an instance hash' do
|
249
|
+
expect(subject).to receive(:api_call)
|
250
|
+
.with("describe-instance", {instanceid: instance_id})
|
251
|
+
.and_return(sample_api_response)
|
252
|
+
result = subject.describe_instance(instance_id)
|
253
|
+
expect(result).to eq expected_instance
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
describe "#terminate_instance" do
|
258
|
+
let(:instance_id) { "234" }
|
259
|
+
let(:sample_api_response) {
|
260
|
+
{
|
261
|
+
"Timestamp" => 1440175812,
|
262
|
+
"terminate-instanceresponse" => {
|
263
|
+
"instancesSet" => {
|
264
|
+
"item" => {
|
265
|
+
"InstanceId" => "154809",
|
266
|
+
"message" => "queued for termination",
|
267
|
+
"result" => "true"
|
268
|
+
}
|
269
|
+
},
|
270
|
+
"requestid" => "4dec8ab5-29e7-48f3-934e-e4bc3101de80"
|
271
|
+
}
|
272
|
+
}
|
273
|
+
}
|
274
|
+
let(:termination_response) {
|
275
|
+
{
|
276
|
+
"InstanceId" => "154809",
|
277
|
+
"message" => "queued for termination",
|
278
|
+
"result" => "true"
|
279
|
+
}
|
280
|
+
}
|
281
|
+
|
282
|
+
it 'calls api_call with terminate-instance and returns a termination response hash' do
|
283
|
+
expect(subject).to receive(:api_call)
|
284
|
+
.with("terminate-instance", {instanceid: instance_id})
|
285
|
+
.and_return(sample_api_response)
|
286
|
+
result = subject.terminate_instance(instance_id)
|
287
|
+
expect(result).to eq termination_response
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
describe "#run_instance" do
|
292
|
+
let(:sample_api_response) {
|
293
|
+
{
|
294
|
+
"Timestamp" => 1440018190,
|
295
|
+
"run-instanceresponse" => {
|
296
|
+
"instancesSet" => {
|
297
|
+
"item" => {
|
298
|
+
"instanceid" => "153979",
|
299
|
+
"ip_address" => "45.58.35.251",
|
300
|
+
"password" => "8q%Q6KaQ",
|
301
|
+
"username" => "root"
|
302
|
+
}
|
303
|
+
},
|
304
|
+
"requestid" => "6396399d-cb7d-446a-91c6-1334d0f939d8"
|
305
|
+
}
|
306
|
+
}
|
307
|
+
}
|
308
|
+
let(:run_response) {
|
309
|
+
{
|
310
|
+
"instanceid" => "153979",
|
311
|
+
"ip_address" => "45.58.35.251",
|
312
|
+
"password" => "8q%Q6KaQ",
|
313
|
+
"username" => "root"
|
314
|
+
}
|
315
|
+
}
|
316
|
+
|
317
|
+
|
318
|
+
let(:server_name) {"apitestserver"}
|
319
|
+
let(:image_id) {"ubuntu-14.04_64bit"}
|
320
|
+
let(:plan_name) {"L"}
|
321
|
+
let(:vm_location) {"USEAST2"}
|
322
|
+
|
323
|
+
context "default parameters" do
|
324
|
+
it 'calls the api with the servername, imageid, planname and vm_location' do
|
325
|
+
expect(subject).to receive(:api_call)
|
326
|
+
.with("run-instance", {servername: server_name, imageid: image_id, planname: plan_name, vm_location: vm_location})
|
327
|
+
.and_return(sample_api_response)
|
328
|
+
result = subject.run_instance(server_name, plan_name, vm_location, {image_id: image_id})
|
329
|
+
expect(result).to eq run_response
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
context "use clone_image instead of image_id" do
|
334
|
+
let(:clone_image) {"17-145607"}
|
335
|
+
|
336
|
+
it 'calls the api with the servername, cloneimage, planname and vm_location' do
|
337
|
+
expect(subject).to receive(:api_call)
|
338
|
+
.with("run-instance", {servername: server_name, cloneimage: clone_image, planname: plan_name, vm_location: vm_location})
|
339
|
+
.and_return(sample_api_response)
|
340
|
+
result = subject.run_instance(server_name, plan_name, vm_location, {clone_image: clone_image})
|
341
|
+
expect(result).to eq run_response
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
context "no image id or clone image are provided" do
|
346
|
+
it 'raises an error when all the required arguments aren\'t specified' do
|
347
|
+
expect{subject.run_instance(server_name, plan_name, vm_location)}
|
348
|
+
.to raise_error(ArgumentError)
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
context "additional options" do
|
353
|
+
let(:enable_backup) { true }
|
354
|
+
let(:server_quantity) { 2 }
|
355
|
+
let(:key_id) { "yt9p4y64f7dem3e" }
|
356
|
+
|
357
|
+
it 'calls the api with the default arguments, plus enablebackup, serverqty and key_id' do
|
358
|
+
expect(subject).to receive(:api_call)
|
359
|
+
.with("run-instance", {
|
360
|
+
servername: server_name, imageid: image_id, planname: plan_name, vm_location: vm_location,
|
361
|
+
enablebackup: enable_backup, serverqty: server_quantity, key_id: key_id})
|
362
|
+
.and_return(sample_api_response)
|
363
|
+
result = subject.run_instance(server_name, plan_name, vm_location, {
|
364
|
+
image_id: image_id, enable_backup: enable_backup, server_quantity: server_quantity, key_id: key_id
|
365
|
+
})
|
366
|
+
expect(result).to eq run_response
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
describe "#describe_images" do
|
372
|
+
let(:sample_api_response) {
|
373
|
+
{
|
374
|
+
"Timestamp" => 1439933643,
|
375
|
+
"describe-imageresponse" => {
|
376
|
+
"imagesset" => {
|
377
|
+
"1item" => {
|
378
|
+
"architecture" => "x86_64",
|
379
|
+
"displayname" => "Ubuntu 14.04 LTS Server 64-Bit",
|
380
|
+
"image_type" => "os",
|
381
|
+
"imageid" => "ubuntu-14.04_64bit",
|
382
|
+
"ostype" => "linux",
|
383
|
+
"owner" => "atlantic",
|
384
|
+
"platform" => "linux",
|
385
|
+
"version" => "14.04 LTS"
|
386
|
+
}
|
387
|
+
},
|
388
|
+
"requestid" => "eb221f31-d023-452d-a7e9-9614fc575a9d"
|
389
|
+
}
|
390
|
+
}
|
391
|
+
}
|
392
|
+
let(:image_descriptions) {
|
393
|
+
[
|
394
|
+
{
|
395
|
+
"architecture" => "x86_64",
|
396
|
+
"displayname" => "Ubuntu 14.04 LTS Server 64-Bit",
|
397
|
+
"image_type" => "os",
|
398
|
+
"imageid" => "ubuntu-14.04_64bit",
|
399
|
+
"ostype" => "linux",
|
400
|
+
"owner" => "atlantic",
|
401
|
+
"platform" => "linux",
|
402
|
+
"version" => "14.04 LTS"
|
403
|
+
}
|
404
|
+
]
|
405
|
+
}
|
406
|
+
|
407
|
+
context 'default options' do
|
408
|
+
it 'calls api_call with describe-image and returns a list of image hashes' do
|
409
|
+
expect(subject).to receive(:api_call)
|
410
|
+
.with("describe-image")
|
411
|
+
.and_return(sample_api_response)
|
412
|
+
result = subject.describe_images
|
413
|
+
expect(result).to eq image_descriptions
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
context 'optional imageid' do
|
418
|
+
let(:image_id) { "ubuntu-14.04_64bit" }
|
419
|
+
it 'calls api_call with describe-image and a image_id string and returns a list of image hashes' do
|
420
|
+
expect(subject).to receive(:api_call)
|
421
|
+
.with("describe-image", {imageid: image_id})
|
422
|
+
.and_return(sample_api_response)
|
423
|
+
result = subject.describe_images({image_id: image_id})
|
424
|
+
expect(result).to eq image_descriptions
|
425
|
+
end
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
describe "#describe_plans" do
|
430
|
+
let(:sample_api_response) {
|
431
|
+
{
|
432
|
+
"Timestamp" => 1439932362,
|
433
|
+
"describe-planresponse" => {
|
434
|
+
"plans" => {
|
435
|
+
"1item" => {
|
436
|
+
"bandwidth" => 600,
|
437
|
+
"centos_capable" => "Y",
|
438
|
+
"cpanel_capable" => "Y",
|
439
|
+
"disk" => "100",
|
440
|
+
"display_bandwidth" => "600Mbits",
|
441
|
+
"display_disk" => "100GB",
|
442
|
+
"display_ram" => "4GB",
|
443
|
+
"free_transfer" => "5",
|
444
|
+
"num_cpu" => "2",
|
445
|
+
"ostype" => "linux",
|
446
|
+
"plan_name" => "L",
|
447
|
+
"platform" => "linux",
|
448
|
+
"ram" => "4096",
|
449
|
+
"rate_per_hr" => 0.0547
|
450
|
+
}
|
451
|
+
},
|
452
|
+
"requestid" => "4aae48ae-af7b-4bbd-9309-58aadbfd02d3"
|
453
|
+
}
|
454
|
+
}
|
455
|
+
}
|
456
|
+
let(:plan_descriptions) {
|
457
|
+
[
|
458
|
+
{
|
459
|
+
"bandwidth" => 600,
|
460
|
+
"centos_capable" => "Y",
|
461
|
+
"cpanel_capable" => "Y",
|
462
|
+
"disk" => "100",
|
463
|
+
"display_bandwidth" => "600Mbits",
|
464
|
+
"display_disk" => "100GB",
|
465
|
+
"display_ram" => "4GB",
|
466
|
+
"free_transfer" => "5",
|
467
|
+
"num_cpu" => "2",
|
468
|
+
"ostype" => "linux",
|
469
|
+
"plan_name" => "L",
|
470
|
+
"platform" => "linux",
|
471
|
+
"ram" => "4096",
|
472
|
+
"rate_per_hr" => 0.0547
|
473
|
+
}
|
474
|
+
]
|
475
|
+
}
|
476
|
+
|
477
|
+
context 'default options' do
|
478
|
+
it 'calls api_call with describe-plan and returns a list of plan hashes' do
|
479
|
+
expect(subject).to receive(:api_call)
|
480
|
+
.with("describe-plan")
|
481
|
+
.and_return(sample_api_response)
|
482
|
+
result = subject.describe_plans
|
483
|
+
expect(result).to eq plan_descriptions
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
context 'optional arguments' do
|
488
|
+
let(:plan_name) { "L" }
|
489
|
+
let(:platform) { "linux" }
|
490
|
+
it 'calls api_call with describe-plan plan_name and platform and returns a list of image hashes' do
|
491
|
+
expect(subject).to receive(:api_call)
|
492
|
+
.with("describe-plan", {plan_name: plan_name, platform: platform})
|
493
|
+
.and_return(sample_api_response)
|
494
|
+
result = subject.describe_plans({plan_name: plan_name, platform: platform})
|
495
|
+
expect(result).to eq plan_descriptions
|
496
|
+
end
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
describe "#list_ssh_keys" do
|
501
|
+
let(:sample_api_response) {
|
502
|
+
{
|
503
|
+
"Timestamp" => 1457105502,
|
504
|
+
"list-sshkeysresponse" => {
|
505
|
+
"KeysSet" => {
|
506
|
+
"item" => {
|
507
|
+
"key_id" => "yt9p4y64f7dem3e",
|
508
|
+
"key_name" => "My Public SSH Key",
|
509
|
+
"public_key" => "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAsdfAn4sozeeBHWCv6B/tkTcUFz47fg48FgasdfasdfJNp4T5Fyq+3/6BA6fdZoI9skdudkfy3n6IUxHr5fwIUD0tn7QNsn5jp9rpjVRuXqoHUP3OYh6ZSlPBnsVmRNOI2ZWiBqMCIsWaeUkenVfnmvLZ/eMVwoKiDhakHs1dvaB8X4kEc7DnXKDZEyy0hAb+Eei8ppUqs9uMq+utXLEMCk0cPMTtqMialvk1pnz2lMuVPw1HGNRh2mjyGI7+6DoPCHaYurDQMXcyfF+05pSpBZCQAVJWvZFzivGfzUOAc4bgFBLznECQ== user@workstation-206"
|
510
|
+
}
|
511
|
+
},
|
512
|
+
"requestid" => "acea7888-a756-4ea1-b9db-6d2267673247"
|
513
|
+
}
|
514
|
+
}
|
515
|
+
}
|
516
|
+
let(:ssh_keys) {
|
517
|
+
[
|
518
|
+
{
|
519
|
+
"key_id" => "yt9p4y64f7dem3e",
|
520
|
+
"key_name" => "My Public SSH Key",
|
521
|
+
"public_key" => "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAsdfAn4sozeeBHWCv6B/tkTcUFz47fg48FgasdfasdfJNp4T5Fyq+3/6BA6fdZoI9skdudkfy3n6IUxHr5fwIUD0tn7QNsn5jp9rpjVRuXqoHUP3OYh6ZSlPBnsVmRNOI2ZWiBqMCIsWaeUkenVfnmvLZ/eMVwoKiDhakHs1dvaB8X4kEc7DnXKDZEyy0hAb+Eei8ppUqs9uMq+utXLEMCk0cPMTtqMialvk1pnz2lMuVPw1HGNRh2mjyGI7+6DoPCHaYurDQMXcyfF+05pSpBZCQAVJWvZFzivGfzUOAc4bgFBLznECQ== user@workstation-206"
|
522
|
+
}
|
523
|
+
]
|
524
|
+
}
|
525
|
+
|
526
|
+
it 'calls api_call with list-sshkeys and returns a list of ssh key hashes' do
|
527
|
+
expect(subject).to receive(:api_call)
|
528
|
+
.with("list-sshkeys")
|
529
|
+
.and_return(sample_api_response)
|
530
|
+
result = subject.list_ssh_keys
|
531
|
+
expect(result).to eq ssh_keys
|
532
|
+
end
|
533
|
+
end
|
534
|
+
|
535
|
+
describe '#api_call' do
|
536
|
+
it 'passes on the action' do
|
537
|
+
expect(transport).to receive(:send_request).with(a_hash_including(Action: 'some-action'))
|
538
|
+
subject.send(:api_call, 'some-action')
|
539
|
+
end
|
540
|
+
|
541
|
+
it 'includes a valid signature, public key, and timestamp' do
|
542
|
+
allow(subject).to receive(:generate_request_id_tuple).and_return([ sample_timestamp, sample_request_id] )
|
543
|
+
|
544
|
+
expect(transport).to receive(:send_request).with(a_hash_including(Signature: sample_signature, ACSAccessKeyId: access_key, Timestamp: sample_timestamp))
|
545
|
+
subject.send(:api_call, 'some-action')
|
546
|
+
end
|
547
|
+
|
548
|
+
it 'passes on any arguments' do
|
549
|
+
expect(transport).to receive(:send_request).with(a_hash_including(Value1: 'some-value-1', Value2: 'some-value-2'))
|
550
|
+
subject.send(:api_call, 'someother-action', {:Value1 => "some-value-1", :Value2 => "some-value-2"})
|
551
|
+
end
|
552
|
+
|
553
|
+
it 'raises an exception if there is an error' do
|
554
|
+
expect(transport).to receive(:send_request).and_return( JSON.parse('{"error":{"message": "Some error occurred"}}') )
|
555
|
+
expect{subject.send(:api_call, 'some-erroneous-action')}.to raise_error(AtlanticNetException)
|
556
|
+
end
|
557
|
+
end
|
558
|
+
|
559
|
+
describe '#generate_request_id' do
|
560
|
+
it 'Uses Time to return epoc timestamp' do
|
561
|
+
expect(Time).to receive(:now).and_return(double(:ts, to_i: 100))
|
562
|
+
expect(subject.send(:generate_request_id_tuple).first).to eq(100)
|
563
|
+
end
|
564
|
+
|
565
|
+
it 'Returns a valid uuid for the request_id' do
|
566
|
+
request_id = subject.send(:generate_request_id_tuple).last
|
567
|
+
expect{ UUIDTools::UUID.parse(request_id)}.not_to raise_error
|
568
|
+
end
|
569
|
+
|
570
|
+
it 'Returns different request_ids for subsequent calls' do
|
571
|
+
request_id1 = subject.send(:generate_request_id_tuple).last
|
572
|
+
request_id2 = subject.send(:generate_request_id_tuple).last
|
573
|
+
expect(request_id1).not_to eq (request_id2)
|
574
|
+
end
|
575
|
+
end
|
576
|
+
end
|
577
|
+
|
578
|
+
describe AtlanticNet::HttpTransport do
|
579
|
+
let(:transport) { AtlanticNet::HttpTransport.new }
|
580
|
+
let(:sample_data) { {"arg1" => "value1", "arg2" => "value2"} }
|
581
|
+
let(:sample_response) { {"result1" => "response_value_1", "result2" => "response_value_2" }}
|
582
|
+
|
583
|
+
describe "#send_request" do
|
584
|
+
it "Passes the arguments and parses the response" do
|
585
|
+
stub_request(:get, "https://cloudapi.atlantic.net").with(query: sample_data).to_return(body: sample_response.to_json)
|
586
|
+
result = transport.send_request(sample_data)
|
587
|
+
expect(result).to eq sample_response
|
588
|
+
end
|
589
|
+
|
590
|
+
it "raises an exception when request is unsuccessful" do
|
591
|
+
stub_request(:get, "https://cloudapi.atlantic.net").to_return(status: 404)
|
592
|
+
expect{transport.send_request({})}.to raise_error(AtlanticNetException)
|
593
|
+
end
|
594
|
+
end
|
595
|
+
end
|
596
|
+
|
597
|
+
describe AtlanticNetException do
|
598
|
+
let(:atlantic_net_instance) { double }
|
599
|
+
let(:api_response) { double }
|
600
|
+
let(:message) { "an error message" }
|
601
|
+
|
602
|
+
it 'Has the message, instance and api_response accessible' do
|
603
|
+
atlantic_net_exception = AtlanticNetException.new(atlantic_net_instance, api_response, message)
|
604
|
+
expect(atlantic_net_exception.atlantic_net_instance).to eq atlantic_net_instance
|
605
|
+
expect(atlantic_net_exception.api_response).to eq api_response
|
606
|
+
expect(atlantic_net_exception.message).to eq message
|
607
|
+
end
|
608
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require "simplecov"
|
2
|
+
require "coveralls"
|
3
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
4
|
+
SimpleCov::Formatter::HTMLFormatter,
|
5
|
+
Coveralls::SimpleCov::Formatter
|
6
|
+
]
|
7
|
+
SimpleCov.start { add_filter "/spec/" }
|
8
|
+
|
9
|
+
require "atlantic_net"
|
10
|
+
require "uuidtools"
|
11
|
+
require "webmock/rspec"
|
metadata
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: atlantic_net
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jamie Starke
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-05-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rack-test
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 3.0.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 3.0.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec-given
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: coveralls
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: uuidtools
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: webmock
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: pry
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: pry-nav
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
description: A Ruby wrapper of the Atlantic.net API
|
168
|
+
email:
|
169
|
+
- git@jamiestarke.com
|
170
|
+
executables: []
|
171
|
+
extensions: []
|
172
|
+
extra_rdoc_files: []
|
173
|
+
files:
|
174
|
+
- ".gitignore"
|
175
|
+
- ".travis.yml"
|
176
|
+
- Gemfile
|
177
|
+
- LICENSE
|
178
|
+
- README.md
|
179
|
+
- Rakefile
|
180
|
+
- atlantic_net.gemspec
|
181
|
+
- lib/atlantic_net.rb
|
182
|
+
- spec/atlantic_net_spec.rb
|
183
|
+
- spec/spec_helper.rb
|
184
|
+
homepage: http://github.com/jrstarke/atlantic_net
|
185
|
+
licenses:
|
186
|
+
- MIT
|
187
|
+
metadata: {}
|
188
|
+
post_install_message:
|
189
|
+
rdoc_options: []
|
190
|
+
require_paths:
|
191
|
+
- lib
|
192
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
193
|
+
requirements:
|
194
|
+
- - ">="
|
195
|
+
- !ruby/object:Gem::Version
|
196
|
+
version: '0'
|
197
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - ">="
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
requirements: []
|
203
|
+
rubyforge_project:
|
204
|
+
rubygems_version: 2.4.6
|
205
|
+
signing_key:
|
206
|
+
specification_version: 4
|
207
|
+
summary: A Ruby wrapper of the Atlantic.net API
|
208
|
+
test_files:
|
209
|
+
- spec/atlantic_net_spec.rb
|
210
|
+
- spec/spec_helper.rb
|