softlayer_api 1.0.8 → 2.0.0
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 +4 -4
- data/README.textile +116 -66
- data/examples/{accountInformation.rb → account_info.rb} +6 -4
- data/examples/{createTicket.rb → create_ticket.rb} +6 -3
- data/examples/{openTickets.rb → open_tickets.rb} +6 -4
- data/examples/ticket_info.rb +8 -8
- data/lib/softlayer/APIParameterFilter.rb +131 -0
- data/lib/softlayer/Client.rb +100 -0
- data/lib/softlayer/Config.rb +77 -0
- data/lib/softlayer/ObjectFilter.rb +232 -0
- data/lib/softlayer/Service.rb +321 -0
- data/lib/softlayer/base.rb +11 -7
- data/lib/softlayer/object_mask_helpers.rb +60 -13
- data/lib/softlayer_api.rb +6 -1
- metadata +21 -17
- data/lib/softlayer/service.rb +0 -467
data/lib/softlayer_api.rb
CHANGED
@@ -22,4 +22,9 @@
|
|
22
22
|
|
23
23
|
require 'softlayer/base'
|
24
24
|
require 'softlayer/object_mask_helpers'
|
25
|
-
require 'softlayer/
|
25
|
+
require 'softlayer/APIParameterFilter'
|
26
|
+
require 'softlayer/ObjectFilter'
|
27
|
+
require 'softlayer/Config'
|
28
|
+
|
29
|
+
require 'softlayer/Client'
|
30
|
+
require 'softlayer/Service'
|
metadata
CHANGED
@@ -1,47 +1,47 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: softlayer_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- SoftLayer Development Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-05-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.8'
|
20
|
-
- -
|
20
|
+
- - '>='
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: 1.8.1
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
|
-
- -
|
27
|
+
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '1.8'
|
30
|
-
- -
|
30
|
+
- - '>='
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: 1.8.1
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: rake
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
|
-
- -
|
37
|
+
- - '>='
|
38
38
|
- !ruby/object:Gem::Version
|
39
39
|
version: '0'
|
40
40
|
type: :development
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
|
-
- -
|
44
|
+
- - '>='
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '0'
|
47
47
|
description: The softlayer_api gem offers a convenient mechanism for invoking the
|
@@ -51,16 +51,20 @@ executables: []
|
|
51
51
|
extensions: []
|
52
52
|
extra_rdoc_files: []
|
53
53
|
files:
|
54
|
-
- LICENSE.textile
|
55
54
|
- README.textile
|
56
|
-
-
|
57
|
-
-
|
58
|
-
- examples/openTickets.rb
|
59
|
-
- examples/ticket_info.rb
|
55
|
+
- LICENSE.textile
|
56
|
+
- lib/softlayer/APIParameterFilter.rb
|
60
57
|
- lib/softlayer/base.rb
|
58
|
+
- lib/softlayer/Client.rb
|
59
|
+
- lib/softlayer/Config.rb
|
61
60
|
- lib/softlayer/object_mask_helpers.rb
|
62
|
-
- lib/softlayer/
|
61
|
+
- lib/softlayer/ObjectFilter.rb
|
62
|
+
- lib/softlayer/Service.rb
|
63
63
|
- lib/softlayer_api.rb
|
64
|
+
- examples/account_info.rb
|
65
|
+
- examples/create_ticket.rb
|
66
|
+
- examples/open_tickets.rb
|
67
|
+
- examples/ticket_info.rb
|
64
68
|
homepage: http://sldn.softlayer.com/
|
65
69
|
licenses:
|
66
70
|
- MIT
|
@@ -71,17 +75,17 @@ require_paths:
|
|
71
75
|
- lib
|
72
76
|
required_ruby_version: !ruby/object:Gem::Requirement
|
73
77
|
requirements:
|
74
|
-
- -
|
78
|
+
- - '>='
|
75
79
|
- !ruby/object:Gem::Version
|
76
80
|
version: '0'
|
77
81
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
82
|
requirements:
|
79
|
-
- -
|
83
|
+
- - '>='
|
80
84
|
- !ruby/object:Gem::Version
|
81
85
|
version: '0'
|
82
86
|
requirements: []
|
83
87
|
rubyforge_project:
|
84
|
-
rubygems_version: 2.
|
88
|
+
rubygems_version: 2.0.14
|
85
89
|
signing_key:
|
86
90
|
specification_version: 4
|
87
91
|
summary: Library for accessing the SoftLayer portal API
|
data/lib/softlayer/service.rb
DELETED
@@ -1,467 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Copyright (c) 2014 SoftLayer Technologies, Inc. All rights reserved.
|
3
|
-
#
|
4
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
-
# of this software and associated documentation files (the "Software"), to deal
|
6
|
-
# in the Software without restriction, including without limitation the rights
|
7
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
-
# copies of the Software, and to permit persons to whom the Software is
|
9
|
-
# furnished to do so, subject to the following conditions:
|
10
|
-
#
|
11
|
-
# The above copyright notice and this permission notice shall be included in
|
12
|
-
# all copies or substantial portions of the Software.
|
13
|
-
#
|
14
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
-
# THE SOFTWARE.
|
21
|
-
#
|
22
|
-
|
23
|
-
require 'rubygems'
|
24
|
-
require 'net/https'
|
25
|
-
require 'json/add/core'
|
26
|
-
|
27
|
-
module SoftLayer
|
28
|
-
# A subclass of Exception with nothing new provided. This simply provides
|
29
|
-
# a unique type for exceptions from the SoftLayer API
|
30
|
-
class SoftLayerAPIException < RuntimeError
|
31
|
-
end
|
32
|
-
|
33
|
-
# An APIParameterFilter is an intermediary object that understands how
|
34
|
-
# to accept the other API parameter filters and carry their values to
|
35
|
-
# method_missing in Service. Instances of this class are created
|
36
|
-
# internally by the Service in it's handling of a method call and you
|
37
|
-
# should not have to create instances of this class directly.
|
38
|
-
#
|
39
|
-
# Instead, to use an API filter, you add a filter method to the call
|
40
|
-
# chain when you call a method through a SoftLayer::Service
|
41
|
-
#
|
42
|
-
# For example, given a SoftLayer::Service instance called "account_service"
|
43
|
-
# you could take advantage of the API filter that identifies a particular
|
44
|
-
# object known to that service using the 'object_with_id" method :
|
45
|
-
#
|
46
|
-
# account_service.object_with_id(91234).getSomeAttribute
|
47
|
-
#
|
48
|
-
# The invocation of object_with_id will cause an instance of this
|
49
|
-
# class to be instantiated with the service as its target.
|
50
|
-
#
|
51
|
-
class APIParameterFilter
|
52
|
-
attr_accessor :target
|
53
|
-
attr_accessor :parameters
|
54
|
-
|
55
|
-
def initialize
|
56
|
-
@parameters = {}
|
57
|
-
end
|
58
|
-
|
59
|
-
def server_object_id
|
60
|
-
self.parameters[:server_object_id]
|
61
|
-
end
|
62
|
-
|
63
|
-
def server_object_mask
|
64
|
-
self.parameters[:object_mask]
|
65
|
-
end
|
66
|
-
|
67
|
-
def object_with_id(value)
|
68
|
-
merged_object = APIParameterFilter.new;
|
69
|
-
merged_object.target = self.target
|
70
|
-
merged_object.parameters = @parameters.merge({ :server_object_id => value })
|
71
|
-
merged_object
|
72
|
-
end
|
73
|
-
|
74
|
-
def object_mask(*args)
|
75
|
-
merged_object = APIParameterFilter.new;
|
76
|
-
merged_object.target = self.target
|
77
|
-
merged_object.parameters = @parameters.merge({ :object_mask => args }) if args && !args.empty?
|
78
|
-
merged_object
|
79
|
-
end
|
80
|
-
|
81
|
-
def result_limit(limit)
|
82
|
-
merged_object = APIParameterFilter.new;
|
83
|
-
merged_object.target = self.target
|
84
|
-
merged_object.parameters = @parameters.merge({ :result_limit => limit })
|
85
|
-
merged_object
|
86
|
-
end
|
87
|
-
|
88
|
-
def server_result_limit
|
89
|
-
self.parameters[:result_limit]
|
90
|
-
end
|
91
|
-
|
92
|
-
def result_offset(offset)
|
93
|
-
self.parameters[:result_offset] = offset
|
94
|
-
self
|
95
|
-
end
|
96
|
-
|
97
|
-
def server_result_offset
|
98
|
-
self.parameters[:result_offset]
|
99
|
-
end
|
100
|
-
|
101
|
-
def method_missing(method_name, *args, &block)
|
102
|
-
return @target.call_softlayer_api_with_params(method_name, self, args, &block)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
# = SoftLayer API Service
|
107
|
-
#
|
108
|
-
# Instances of this class represent services in the SoftLayer API.
|
109
|
-
#
|
110
|
-
# You create a service with the name of one of the SoftLayer services
|
111
|
-
# (documented on the http://sldn.softlayer.com web site). Once created
|
112
|
-
# you can use the service to make method calls to the SoftLayer API.
|
113
|
-
#
|
114
|
-
# A typical use might look something like
|
115
|
-
#
|
116
|
-
# account_service = SoftLayer::Service("SoftLayer_Account", :username=>"<your user name here>" :api_key=>"<your api key here>")
|
117
|
-
#
|
118
|
-
# then to invoke a method simply call the service:
|
119
|
-
#
|
120
|
-
# account_service.getOpenTickets
|
121
|
-
# => {... lots of information here representing the list of open tickets ...}
|
122
|
-
#
|
123
|
-
class Service
|
124
|
-
# The name of the service that this object calls. Cannot be emtpy or nil.
|
125
|
-
attr_accessor :service_name
|
126
|
-
|
127
|
-
# A username passed as authentication for each request. Cannot be emtpy or nil.
|
128
|
-
attr_accessor :username
|
129
|
-
|
130
|
-
# An API key passed as part of the authentication of each request. Cannot be emtpy or nil.
|
131
|
-
attr_accessor :api_key
|
132
|
-
|
133
|
-
# The base URL for requests that are passed to the server. Cannot be emtpy or nil.
|
134
|
-
attr_accessor :endpoint_url
|
135
|
-
|
136
|
-
# The User-Agent header sent to SoftLayer API.
|
137
|
-
attr_accessor :user_agent
|
138
|
-
|
139
|
-
# Initialize an instance of the Client class. You pass in the service name
|
140
|
-
# and optionally hash arguments specifying how the client should access the
|
141
|
-
# SoftLayer API.
|
142
|
-
#
|
143
|
-
# The following symbols can be used as hash arguments to pass options to the constructor:
|
144
|
-
# - <tt>:username</tt> - a non-empty string providing the username to use for requests to the service
|
145
|
-
# - <tt>:api_key</tt> - a non-empty string providing the api key to use for requests to the service
|
146
|
-
# - <tt>:endpoint_url</tt> - a non-empty string providing the endpoint URL to use for requests to the service
|
147
|
-
#
|
148
|
-
# If any of the options above are missing then the constructor will try to use the corresponding
|
149
|
-
# global variable declared in the SoftLayer Module:
|
150
|
-
# - <tt>$SL_API_USERNAME</tt>
|
151
|
-
# - <tt>$SL_API_KEY</tt>
|
152
|
-
# - <tt>$SL_API_BASE_URL</tt>
|
153
|
-
#
|
154
|
-
def initialize(service_name, options = {})
|
155
|
-
raise SoftLayerAPIException.new("Please provide a service name") if service_name.nil? || service_name.empty?
|
156
|
-
self.service_name = service_name;
|
157
|
-
|
158
|
-
# pick up the username provided in options or the default one from the *globals*
|
159
|
-
self.username = options[:username] || $SL_API_USERNAME || ""
|
160
|
-
|
161
|
-
# pick up the api_key provided in options or the default one from the globals
|
162
|
-
self.api_key = options[:api_key] || $SL_API_KEY || ""
|
163
|
-
|
164
|
-
# pick up the url endpoint from options or the default one in the globals OR the
|
165
|
-
# public endpoint
|
166
|
-
self.endpoint_url = options[:endpoint_url] || $SL_API_BASE_URL || API_PUBLIC_ENDPOINT
|
167
|
-
|
168
|
-
@user_agent = {"User-Agent" => options[:user_agent] || "SoftLayer API Ruby Client #{SoftLayer::VERSION}"}
|
169
|
-
|
170
|
-
if($DEBUG)
|
171
|
-
@method_missing_call_depth = 0
|
172
|
-
end
|
173
|
-
end #initalize
|
174
|
-
|
175
|
-
# Use this to set the user agent string for this API client.
|
176
|
-
def user_agent=(set)
|
177
|
-
self.user_agent['User-Agent'] = set
|
178
|
-
end
|
179
|
-
|
180
|
-
# Use this as part of a method call chain to identify a particular
|
181
|
-
# object as the target of the request. The parameter is the SoftLayer
|
182
|
-
# object identifier you are interested in. For example, this call
|
183
|
-
# would return the ticket whose ID is 35212
|
184
|
-
#
|
185
|
-
# ticket_service.object_with_id(35212).getObject
|
186
|
-
#
|
187
|
-
def object_with_id(object_of_interest)
|
188
|
-
proxy = APIParameterFilter.new
|
189
|
-
proxy.target = self
|
190
|
-
|
191
|
-
return proxy.object_with_id(object_of_interest)
|
192
|
-
end
|
193
|
-
|
194
|
-
# Use this as part of a method call chain to add an object mask to
|
195
|
-
# the request.The arguments to object mask should be the strings
|
196
|
-
# that are the keys of the mask:
|
197
|
-
#
|
198
|
-
# ticket_service.object_mask("createDate", "modifyDate").getObject
|
199
|
-
#
|
200
|
-
# Before being used, the string passed will be url-encoded by this
|
201
|
-
# routine. (i.e. there is no need to url-encode the strings beforehand)
|
202
|
-
#
|
203
|
-
# As an implementation detail, the object_mask becomes part of the
|
204
|
-
# query on the url sent to the API server
|
205
|
-
#
|
206
|
-
def object_mask(*args)
|
207
|
-
proxy = APIParameterFilter.new
|
208
|
-
proxy.target = self
|
209
|
-
|
210
|
-
return proxy.object_mask(*args)
|
211
|
-
end
|
212
|
-
|
213
|
-
def result_limit(limit)
|
214
|
-
proxy = APIParameterFilter.new
|
215
|
-
proxy.target = self
|
216
|
-
return proxy.result_limit(limit)
|
217
|
-
end
|
218
|
-
|
219
|
-
def result_offset(offset)
|
220
|
-
proxy = APIParameterFilter.new
|
221
|
-
proxy.target = self
|
222
|
-
return proxy.result_offset(offset)
|
223
|
-
end
|
224
|
-
|
225
|
-
# This is the primary mechanism by which requests are made. If you call
|
226
|
-
# the service with a method it doesn't understand, it will send a call to
|
227
|
-
# the endpoint for a method of the same name.
|
228
|
-
#
|
229
|
-
def method_missing(method_name, *args, &block)
|
230
|
-
# During development, if you end up with a stray name in some
|
231
|
-
# code, you can end up in an infinite recursive loop as method_missing
|
232
|
-
# tries to resolve that name (believe me... it happens).
|
233
|
-
# This mechanism looks for what it considers to be an unreasonable call
|
234
|
-
# depth and kills the loop quickly.
|
235
|
-
if($DEBUG)
|
236
|
-
@method_missing_call_depth += 1
|
237
|
-
if @method_missing_call_depth > 3 # 3 is somewhat arbitrary... really the call depth should only ever be 1
|
238
|
-
@method_missing_call_depth = 0
|
239
|
-
raise "stop infinite recursion #{method_name}, #{args.inspect}"
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
# if we're in debug mode, we put out a little helpful information
|
244
|
-
puts "SoftLayer::Service#method_missing called #{method_name}, #{args.inspect}" if $DEBUG
|
245
|
-
|
246
|
-
result = call_softlayer_api_with_params(method_name, nil, args, &block);
|
247
|
-
|
248
|
-
if($DEBUG)
|
249
|
-
@method_missing_call_depth -= 1
|
250
|
-
end
|
251
|
-
|
252
|
-
return result
|
253
|
-
end
|
254
|
-
|
255
|
-
# Issue an HTTP request to call the given method from the SoftLayer API with
|
256
|
-
# the parameters and arguments given.
|
257
|
-
#
|
258
|
-
# Parameters are information _about_ the call, the object mask or the
|
259
|
-
# particular object in the SoftLayer API you are calling.
|
260
|
-
#
|
261
|
-
# Arguments are the arguments to the SoftLayer method that you wish to
|
262
|
-
# invoke.
|
263
|
-
#
|
264
|
-
# This is intended to be used in the internal
|
265
|
-
# processing of method_missing and need not be called directly.
|
266
|
-
def call_softlayer_api_with_params(method_name, parameters, args, &block)
|
267
|
-
# find out what URL will invoke the method (with the given parameters)
|
268
|
-
request_url = url_to_call_method(method_name, parameters)
|
269
|
-
|
270
|
-
# marshall the arguments into the http_request
|
271
|
-
request_body = marshall_arguments_for_call(args)
|
272
|
-
|
273
|
-
# construct an HTTP request for that method with the given URL
|
274
|
-
http_request = http_request_for_method(method_name, request_url, request_body);
|
275
|
-
http_request.basic_auth(self.username, self.api_key)
|
276
|
-
|
277
|
-
# Send the url request and recover the results. Parse the response (if any)
|
278
|
-
# as JSON
|
279
|
-
json_results = issue_http_request(request_url, http_request, &block)
|
280
|
-
if json_results
|
281
|
-
# The JSON parser for Ruby parses JSON "Text" according to RFC 4627, but
|
282
|
-
# not JSON values. As a result, 'JSON.parse("true")' yields a parsing
|
283
|
-
# exception. To work around this, we force the result JSON text by
|
284
|
-
# including it in Array markers, then take the first element of the
|
285
|
-
# resulting array as the result of the parsing. This should allow values
|
286
|
-
# like true, false, null, and numbers to parse the same way they would in
|
287
|
-
# a browser.
|
288
|
-
parsed_json = JSON.parse("[ #{json_results} ]")[0]
|
289
|
-
|
290
|
-
# if the results indicate an error, convert it into an exception
|
291
|
-
if parsed_json.kind_of?(Hash) && parsed_json['error']
|
292
|
-
raise SoftLayerAPIException.new(parsed_json['error'])
|
293
|
-
end
|
294
|
-
else
|
295
|
-
parsed_json = nil
|
296
|
-
end
|
297
|
-
|
298
|
-
# return the results, if any
|
299
|
-
return parsed_json
|
300
|
-
end
|
301
|
-
|
302
|
-
# Marshall the arguments into a JSON string suitable for the body of
|
303
|
-
# an HTTP message. This is intended to be used in the internal
|
304
|
-
# processing of method_missing and need not be called directly.
|
305
|
-
def marshall_arguments_for_call(args)
|
306
|
-
request_body = nil;
|
307
|
-
|
308
|
-
if(args && !args.empty?)
|
309
|
-
request_body = {"parameters" => args}.to_json
|
310
|
-
end
|
311
|
-
|
312
|
-
return request_body
|
313
|
-
end
|
314
|
-
|
315
|
-
# Given a method name, determine the appropriate HTTP mechanism
|
316
|
-
# for sending a request to execute that method to the server.
|
317
|
-
# and create a Net::HTTP request of that type. This is intended
|
318
|
-
# to be used in the internal processing of method_missing and
|
319
|
-
# need not be called directly.
|
320
|
-
def http_request_for_method(method_name, method_url, request_body = nil)
|
321
|
-
content_type_header = {"Content-Type" => "application/json"}
|
322
|
-
|
323
|
-
# This is a workaround for a potential problem that arises from mis-using the
|
324
|
-
# API. If you call SoftLayer_Virtual_Guest and you call the getObject method
|
325
|
-
# but pass a virtual guest as a parameter, what happens is the getObject method
|
326
|
-
# is called through an HTTP POST verb and the API creates a new CCI that is a copy
|
327
|
-
# of the one you passed in.
|
328
|
-
#
|
329
|
-
# The counter-intuitive creation of a new CCI is unexpected and, even worse,
|
330
|
-
# is something you can be billed for. To prevent that, we ignore the request
|
331
|
-
# body on a "getObject" call and print out a warning.
|
332
|
-
if (method_name == :getObject) && (nil != request_body) then
|
333
|
-
$stderr.puts "Warning - The getObject method takes no parameters. The parameters you have provided will be ignored."
|
334
|
-
request_body = nil
|
335
|
-
end
|
336
|
-
|
337
|
-
if request_body && !request_body.empty?
|
338
|
-
url_request = Net::HTTP::Post.new(method_url.request_uri(), content_type_header.merge(self.user_agent))
|
339
|
-
else
|
340
|
-
url_request = Net::HTTP::Get.new(method_url.request_uri(), self.user_agent)
|
341
|
-
end
|
342
|
-
|
343
|
-
# This warning should be obsolete as we should be using POST if the user
|
344
|
-
# has provided parameters. I'm going to leave it in, however, on the off
|
345
|
-
# chance that it catches a case we aren't expecting.
|
346
|
-
if request_body && !url_request.request_body_permitted?
|
347
|
-
$stderr.puts("Warning - The HTTP request for #{method_name} does not allow arguments to be passed to the server")
|
348
|
-
else
|
349
|
-
# Otherwise, add the arguments as the body of the request
|
350
|
-
url_request.body = request_body
|
351
|
-
end
|
352
|
-
|
353
|
-
url_request
|
354
|
-
end
|
355
|
-
|
356
|
-
# Connect to the network and request the content of the resource
|
357
|
-
# specified. This is used to do the actual work of connecting
|
358
|
-
# to the SoftLayer servers and exchange data. This is intended
|
359
|
-
# to be used in the internal processing of method_missing and
|
360
|
-
# need not be called directly.
|
361
|
-
def issue_http_request(request_url, http_request, &block)
|
362
|
-
# create and run an SSL request
|
363
|
-
https = Net::HTTP.new(request_url.host, request_url.port)
|
364
|
-
https.use_ssl = (request_url.scheme == "https")
|
365
|
-
|
366
|
-
# This line silences an annoying warning message if you're in debug mode
|
367
|
-
https.verify_mode = OpenSSL::SSL::VERIFY_NONE if $DEBUG
|
368
|
-
|
369
|
-
https.start do |http|
|
370
|
-
|
371
|
-
puts "SoftLayer API issuing an HTTP request for #{request_url}" if $DEBUG
|
372
|
-
|
373
|
-
response = https.request(http_request)
|
374
|
-
|
375
|
-
case response
|
376
|
-
when Net::HTTPSuccess
|
377
|
-
return response.body
|
378
|
-
else
|
379
|
-
# We have an error. It might have a meaningful error message
|
380
|
-
# from the server. Check to see if there is a body and whether
|
381
|
-
# or not that body parses as JSON. If it does, then we return
|
382
|
-
# that as a result (assuming it's an error)
|
383
|
-
json_parses = false
|
384
|
-
body = response.body
|
385
|
-
|
386
|
-
begin
|
387
|
-
if body
|
388
|
-
JSON.parse(body)
|
389
|
-
json_parses = true
|
390
|
-
end
|
391
|
-
rescue => json_parse_exception
|
392
|
-
json_parses = false;
|
393
|
-
end
|
394
|
-
|
395
|
-
# Let the HTTP library generate and raise an exception if
|
396
|
-
# the body was empty or could not be parsed as JSON
|
397
|
-
response.value() if !json_parses
|
398
|
-
|
399
|
-
return body
|
400
|
-
end
|
401
|
-
end
|
402
|
-
end
|
403
|
-
|
404
|
-
# Construct a URL for calling the given method on this endpoint and
|
405
|
-
# expecting a JSON response. This is intended to be used in the internal
|
406
|
-
# processing of method_missing and need not be called directly.
|
407
|
-
def url_to_call_method(method_name, parameters)
|
408
|
-
method_path = method_name.to_s
|
409
|
-
|
410
|
-
# if there's an object ID on the parameters, add that to the URL
|
411
|
-
if(parameters && parameters.server_object_id)
|
412
|
-
method_path = parameters.server_object_id.to_s + "/" + method_path
|
413
|
-
end
|
414
|
-
|
415
|
-
# tag ".json" onto the method path (if it's not already there)
|
416
|
-
method_path.sub!(%r|(\.json){0,1}$|, ".json")
|
417
|
-
|
418
|
-
# put the whole thing together into a URL
|
419
|
-
# (reusing a variation on the clever regular expression above. This one appends a "slash"
|
420
|
-
# to the service name if theres not already one there otherwise. Without it URI.join
|
421
|
-
# doesn't do the right thing)
|
422
|
-
uri = URI.join(self.endpoint_url, self.service_name.sub(%r{/*$},"/"), method_path)
|
423
|
-
|
424
|
-
query_string = nil
|
425
|
-
|
426
|
-
if(parameters && parameters.server_object_mask)
|
427
|
-
mask_value = parameters.server_object_mask.to_sl_object_mask.map { |mask_key| URI.encode(mask_key.to_s.strip) }.join(";")
|
428
|
-
query_string = "objectMask=#{mask_value}"
|
429
|
-
end
|
430
|
-
|
431
|
-
if (parameters && parameters.server_result_limit)
|
432
|
-
resultLimit = parameters.server_result_limit
|
433
|
-
resultOffset = parameters.server_result_offset
|
434
|
-
resultOffset = 0 if resultOffset.nil?
|
435
|
-
limit_string = "resultLimit=#{resultOffset},#{resultLimit}"
|
436
|
-
if query_string.nil?
|
437
|
-
query_string = limit_string
|
438
|
-
else
|
439
|
-
query_string << "&#{limit_string}"
|
440
|
-
end
|
441
|
-
end
|
442
|
-
|
443
|
-
uri.query = query_string
|
444
|
-
|
445
|
-
return uri
|
446
|
-
end
|
447
|
-
|
448
|
-
# Change the username. The username cannot be nil or the empty string.
|
449
|
-
def username= (name)
|
450
|
-
raise SoftLayerAPIException.new("Please provide a username") if name.nil? || name.empty?
|
451
|
-
@username = name.strip
|
452
|
-
end
|
453
|
-
|
454
|
-
# Change the api_key. It cannot be nil or the empty string.
|
455
|
-
def api_key= (new_key)
|
456
|
-
raise SoftLayerAPIException.new("Please provide an api_key") if new_key.nil? || new_key.empty?
|
457
|
-
@api_key = new_key.strip
|
458
|
-
end
|
459
|
-
|
460
|
-
# Change the endpoint_url. It cannot be nil or the empty string.
|
461
|
-
def endpoint_url= (new_url)
|
462
|
-
raise SoftLayerAPIException.new("The endpoint url cannot be nil or empty") if new_url.nil? || new_url.empty?
|
463
|
-
@endpoint_url = new_url.strip
|
464
|
-
end
|
465
|
-
end # class Service
|
466
|
-
end # module SoftLayer
|
467
|
-
|