softlayer_api 2.0.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.textile +36 -0
- data/README.textile +17 -7
- data/examples/account_info.rb +6 -3
- data/examples/account_servers.rb +48 -0
- data/examples/create_ticket.rb +33 -22
- data/examples/open_tickets.rb +14 -19
- data/examples/order_bare_metal_package.rb +154 -0
- data/examples/order_virtual_server.rb +85 -0
- data/examples/ticket_info.rb +13 -14
- data/lib/softlayer/APIParameterFilter.rb +100 -23
- data/lib/softlayer/Account.rb +140 -0
- data/lib/softlayer/BareMetalServer.rb +233 -0
- data/lib/softlayer/BareMetalServerOrder.rb +227 -0
- data/lib/softlayer/BareMetalServerOrder_Package.rb +162 -0
- data/lib/softlayer/Client.rb +54 -9
- data/lib/softlayer/Config.rb +2 -3
- data/lib/softlayer/DynamicAttribute.rb +170 -0
- data/lib/softlayer/ModelBase.rb +141 -0
- data/lib/softlayer/ObjectFilter.rb +61 -21
- data/lib/softlayer/ObjectMaskParser.rb +157 -0
- data/lib/softlayer/ObjectMaskProperty.rb +83 -0
- data/lib/softlayer/ObjectMaskToken.rb +107 -0
- data/lib/softlayer/ObjectMaskTokenizer.rb +88 -0
- data/lib/softlayer/ProductItemCategory.rb +137 -0
- data/lib/softlayer/ProductPackage.rb +196 -0
- data/lib/softlayer/Server.rb +245 -0
- data/lib/softlayer/Service.rb +12 -9
- data/lib/softlayer/Ticket.rb +210 -0
- data/lib/softlayer/VirtualServer.rb +388 -0
- data/lib/softlayer/VirtualServerOrder.rb +263 -0
- data/lib/softlayer/base.rb +9 -9
- data/lib/softlayer/object_mask_helpers.rb +46 -18
- data/lib/softlayer_api.rb +15 -0
- metadata +49 -15
@@ -0,0 +1,196 @@
|
|
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
|
+
module SoftLayer
|
24
|
+
##
|
25
|
+
# Each SoftLayer ProductPackage provides information about ordering a product
|
26
|
+
# or service from SoftLayer.
|
27
|
+
#
|
28
|
+
# === Product Item Categories
|
29
|
+
# A important companion to Product Packages are ProductItemCategories.
|
30
|
+
# Each ProductItemCategory represents a set of options that you may choose from when
|
31
|
+
# configuring an attribute of the product or service you are ordering.
|
32
|
+
#
|
33
|
+
# ProductItemCategories are identified by +categoryCode+. Examples of category codes
|
34
|
+
# include 'os', 'ram', and 'port_speed'.
|
35
|
+
#
|
36
|
+
# For example, in a package for ordering a server, the 'os' ProductItemCategory contains
|
37
|
+
# the available choices for operating systems that may be provisioned on the server.
|
38
|
+
#
|
39
|
+
# When you construct an order based on that package, you will make one selection from
|
40
|
+
# the 'os' category and put it into the order.
|
41
|
+
#
|
42
|
+
# === Package Configuration
|
43
|
+
# A package also has a Configuration. A Configuration specifies which
|
44
|
+
# Categories are valid in an order and, more importantly, which Categories
|
45
|
+
# are **required** in any order that uses the ProductPackage.
|
46
|
+
#
|
47
|
+
# When constructing an order, you **must** provide an option for each of the Categories
|
48
|
+
# that the Configuration marks as required (and you must supply a value even if the
|
49
|
+
# Category only has one choice)
|
50
|
+
#
|
51
|
+
class ProductPackage < ModelBase
|
52
|
+
include ::SoftLayer::DynamicAttribute
|
53
|
+
|
54
|
+
##
|
55
|
+
# A friendly, readable name for the package
|
56
|
+
sl_attr :name
|
57
|
+
|
58
|
+
##
|
59
|
+
# The list of locations where this product package is available.
|
60
|
+
sl_attr :availableLocations
|
61
|
+
|
62
|
+
##
|
63
|
+
# The set of product categories needed to make an order for this product package.
|
64
|
+
#
|
65
|
+
sl_dynamic_attr :configuration do |resource|
|
66
|
+
resource.should_update? do
|
67
|
+
# only retrieved once per instance
|
68
|
+
@configuration == nil
|
69
|
+
end
|
70
|
+
|
71
|
+
resource.to_update do
|
72
|
+
#
|
73
|
+
# We call +SoftLayer_Product_Package+ to get the configuration for this package.
|
74
|
+
#
|
75
|
+
# Unfortunately, even though this call includes +SoftLayer_Product_Item_Category+ entities, it does not have the context
|
76
|
+
# needed to find the active price items for that category.
|
77
|
+
#
|
78
|
+
# Instead, we make a second call, this time to +SoftLayer_Product_Package::getCategories+. That method incorporates a complex
|
79
|
+
# filtering mechanism on the server side to give us a list of the categories, groups, and prices that are valid for the current
|
80
|
+
# account at the current time. We construct the ProductItemCategory objects from the results we get back.
|
81
|
+
#
|
82
|
+
configuration_data = softlayer_client['Product_Package'].object_with_id(self.id).object_mask("mask[isRequired,itemCategory.categoryCode]").getConfiguration()
|
83
|
+
|
84
|
+
# We sort of invert the information and create a map from category codes to a boolean representing
|
85
|
+
# whether or not they are required.
|
86
|
+
required_by_category_code = configuration_data.inject({}) do |required_by_category_code, config_category|
|
87
|
+
required_by_category_code[config_category['itemCategory']['categoryCode']] = (config_category['isRequired'] != 0)
|
88
|
+
required_by_category_code
|
89
|
+
end
|
90
|
+
|
91
|
+
# This call to getCategories is the one that does lots of fancy back-end filtering for us
|
92
|
+
categories_data = softlayer_client['Product_Package'].object_with_id(self.id).getCategories()
|
93
|
+
|
94
|
+
# Run though the categories and for each one that's in our config, create a SoftLayer::ProductItemCategory object.
|
95
|
+
# Conveniently the +keys+ of the required_by_category_code gives us a list of the category codes in the configuration
|
96
|
+
config_categories = required_by_category_code.keys
|
97
|
+
categories_data.collect do |category_data|
|
98
|
+
if config_categories.include? category_data['categoryCode']
|
99
|
+
SoftLayer::ProductItemCategory.new(softlayer_client, category_data, required_by_category_code[category_data['categoryCode']])
|
100
|
+
else
|
101
|
+
nil
|
102
|
+
end
|
103
|
+
end.compact
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
##
|
108
|
+
# Returns an array of the required categories in this package
|
109
|
+
def required_categories
|
110
|
+
configuration.select { |category| category.required? }
|
111
|
+
end
|
112
|
+
|
113
|
+
##
|
114
|
+
# Returns the product category with the given category code (or nil if one cannot be found)
|
115
|
+
def category(category_code)
|
116
|
+
configuration.find { |category| category.categoryCode == category_code }
|
117
|
+
end
|
118
|
+
|
119
|
+
def datacenter_options
|
120
|
+
availableLocations.collect { |location_data| location_data["location"]["name"] }
|
121
|
+
end
|
122
|
+
|
123
|
+
##
|
124
|
+
# Given a datacenter name that was returned by datacenter_options, use information
|
125
|
+
# in the package to retrieve a location id.
|
126
|
+
def location_id_for_datacenter_name(datacenter_name)
|
127
|
+
location_data = availableLocations.find { |location_data| location_data["location"]["name"] == datacenter_name }
|
128
|
+
location_data["locationId"]
|
129
|
+
end
|
130
|
+
|
131
|
+
def service
|
132
|
+
softlayer_client['Product_Package'].object_with_id(self.id)
|
133
|
+
end
|
134
|
+
|
135
|
+
##
|
136
|
+
# Requests a list (array) of ProductPackages whose key names match the
|
137
|
+
# one passed in.
|
138
|
+
#
|
139
|
+
def self.packages_with_key_name(key_name, client = nil)
|
140
|
+
softlayer_client = client || Client.default_client
|
141
|
+
raise "#{__method__} requires a client but none was given and Client::default_client is not set" if !softlayer_client
|
142
|
+
|
143
|
+
filter = SoftLayer::ObjectFilter.build('type.keyName') { is(key_name) }
|
144
|
+
filtered_service = softlayer_client['Product_Package'].object_filter(filter).object_mask(self.default_object_mask('mask'))
|
145
|
+
packages_data = filtered_service.getAllObjects
|
146
|
+
packages_data.collect { |package_data| ProductPackage.new(softlayer_client, package_data) }
|
147
|
+
end
|
148
|
+
|
149
|
+
##
|
150
|
+
# Requests a list (array) of ProductPackages whose key names match the
|
151
|
+
# one passed in.
|
152
|
+
#
|
153
|
+
def self.package_with_id(package_id, client = nil)
|
154
|
+
softlayer_client = client || Client.default_client
|
155
|
+
raise "#{__method__} requires a client but none was given and Client::default_client is not set" if !softlayer_client
|
156
|
+
|
157
|
+
package_data = softlayer_client['Product_Package'].object_with_id(package_id).object_mask(self.default_object_mask('mask')).getObject
|
158
|
+
ProductPackage.new(softlayer_client, package_data)
|
159
|
+
end
|
160
|
+
|
161
|
+
##
|
162
|
+
# Returns the ProductPackage of the package used to order virtual servers
|
163
|
+
# At the time of this writing, the code assumes this package is unique
|
164
|
+
#
|
165
|
+
# 'VIRTUAL_SERVER_INSTANCE' is a "well known" constant for this purpose
|
166
|
+
def self.virtual_server_package(client = nil)
|
167
|
+
packages_with_key_name('VIRTUAL_SERVER_INSTANCE', client).first
|
168
|
+
end
|
169
|
+
|
170
|
+
##
|
171
|
+
# Returns the ProductPackage of the package used to order Bare Metal Servers
|
172
|
+
# with simplified configuration options.
|
173
|
+
#
|
174
|
+
# At the time of this writing, the code assumes this package is unique
|
175
|
+
#
|
176
|
+
# 'BARE_METAL_CORE' is a "well known" constant for this purpose
|
177
|
+
def self.bare_metal_instance_package(client = nil)
|
178
|
+
packages_with_key_name('BARE_METAL_CORE', client).first
|
179
|
+
end
|
180
|
+
|
181
|
+
##
|
182
|
+
# Returns an array of ProductPackages, each of which can be used
|
183
|
+
# as the foundation to order a bare metal server.
|
184
|
+
#
|
185
|
+
# 'BARE_METAL_CPU' is a "well known" constant for this purpose
|
186
|
+
def self.bare_metal_server_packages(client = nil)
|
187
|
+
packages_with_key_name('BARE_METAL_CPU', client)
|
188
|
+
end
|
189
|
+
|
190
|
+
protected
|
191
|
+
|
192
|
+
def self.default_object_mask(root)
|
193
|
+
"#{root}[id,name,description,availableLocations.location]"
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end # SoftLayer
|
@@ -0,0 +1,245 @@
|
|
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
|
+
module SoftLayer
|
24
|
+
# Server is the base class for VirtualServer and BareMetalServer.
|
25
|
+
# It implements some functionality common to both those classes.
|
26
|
+
#
|
27
|
+
# Server is an abstract class and you should not create them
|
28
|
+
# directly.
|
29
|
+
#
|
30
|
+
# While VirtualServer and BareMetalServer each have analogs
|
31
|
+
# in the SoftLayer API, those analogs do not share a direct
|
32
|
+
# ancestry. As a result there is no SoftLayer API analog
|
33
|
+
# to this class.
|
34
|
+
class Server < SoftLayer::ModelBase
|
35
|
+
|
36
|
+
##
|
37
|
+
# :attr_reader:
|
38
|
+
# The host name SoftLayer has stored for the server
|
39
|
+
sl_attr :hostname
|
40
|
+
|
41
|
+
##
|
42
|
+
# :attr_reader:
|
43
|
+
# The domain name SoftLayer has stored for the server
|
44
|
+
sl_attr :domain
|
45
|
+
|
46
|
+
##
|
47
|
+
# :attr_reader:
|
48
|
+
# A convenience attribute that combines the hostname and domain name
|
49
|
+
sl_attr :fullyQualifiedDomainName
|
50
|
+
|
51
|
+
##
|
52
|
+
# :attr_reader:
|
53
|
+
# The data center where the server is located
|
54
|
+
sl_attr :datacenter
|
55
|
+
|
56
|
+
##
|
57
|
+
# :attr_reader:
|
58
|
+
# The IP address of the primary public interface for the server
|
59
|
+
sl_attr :primary_public_ip, "primaryIpAddress"
|
60
|
+
|
61
|
+
##
|
62
|
+
# :attr_reader:
|
63
|
+
# The IP address of the primary private interface for the server
|
64
|
+
sl_attr :primary_private_ip, "primaryBackendIpAddress"
|
65
|
+
|
66
|
+
##
|
67
|
+
# :attr_reader:
|
68
|
+
# Notes about these server (for use by the customer)
|
69
|
+
sl_attr :notes
|
70
|
+
|
71
|
+
##
|
72
|
+
# Construct a server from the given client using the network data found in +network_hash+
|
73
|
+
#
|
74
|
+
# Most users should not have to call this method directly. Instead you should access the
|
75
|
+
# servers property of an Account object, or use methods like BareMetalServer#find_servers
|
76
|
+
# or VirtualServer#find_servers
|
77
|
+
#
|
78
|
+
def initialize(softlayer_client, network_hash)
|
79
|
+
if self.class == Server
|
80
|
+
raise RuntimeError, "The Server class is an abstract base class and should not be instantiated directly"
|
81
|
+
else
|
82
|
+
super
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# Make an API request to SoftLayer and return the latest properties hash
|
88
|
+
# for this object.
|
89
|
+
def softlayer_properties(object_mask = nil)
|
90
|
+
my_service = self.service
|
91
|
+
|
92
|
+
if(object_mask)
|
93
|
+
my_service = my_service.object_mask(object_mask)
|
94
|
+
else
|
95
|
+
my_service = my_service.object_mask(self.class.default_object_mask.to_sl_object_mask)
|
96
|
+
end
|
97
|
+
|
98
|
+
my_service.getObject()
|
99
|
+
end
|
100
|
+
|
101
|
+
##
|
102
|
+
# Change the notes of the server
|
103
|
+
# raises ArgumentError if you pass nil as the notes
|
104
|
+
def notes=(new_notes)
|
105
|
+
raise ArgumentError.new("The new notes cannot be nil") unless new_notes
|
106
|
+
|
107
|
+
edit_template = {
|
108
|
+
"notes" => new_notes
|
109
|
+
}
|
110
|
+
|
111
|
+
self.service.editObject(edit_template)
|
112
|
+
self.refresh_details()
|
113
|
+
end
|
114
|
+
|
115
|
+
##
|
116
|
+
# Change the user metadata for the server.
|
117
|
+
#
|
118
|
+
def user_metadata=(new_metadata)
|
119
|
+
raise ArgumentError.new("Cannot set user metadata to nil") unless new_metadata
|
120
|
+
self.service.setUserMetadata([new_metadata])
|
121
|
+
self.refresh_details()
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# Change the hostname of this server
|
126
|
+
# Raises an ArgumentError if the new hostname is nil or empty
|
127
|
+
#
|
128
|
+
def set_hostname!(new_hostname)
|
129
|
+
raise ArgumentError.new("The new hostname cannot be nil") unless new_hostname
|
130
|
+
raise ArgumentError.new("The new hostname cannot be empty") if new_hostname.empty?
|
131
|
+
|
132
|
+
edit_template = {
|
133
|
+
"hostname" => new_hostname
|
134
|
+
}
|
135
|
+
|
136
|
+
self.service.editObject(edit_template)
|
137
|
+
self.refresh_details()
|
138
|
+
end
|
139
|
+
|
140
|
+
##
|
141
|
+
# Change the domain of this server
|
142
|
+
#
|
143
|
+
# Raises an ArgumentError if the new domain is nil or empty
|
144
|
+
# no further validation is done on the domain name
|
145
|
+
#
|
146
|
+
def set_domain!(new_domain)
|
147
|
+
raise ArgumentError.new("The new hostname cannot be nil") unless new_domain
|
148
|
+
raise ArgumentError.new("The new hostname cannot be empty") if new_domain.empty?
|
149
|
+
|
150
|
+
edit_template = {
|
151
|
+
"domain" => new_domain
|
152
|
+
}
|
153
|
+
|
154
|
+
self.service.editObject(edit_template)
|
155
|
+
self.refresh_details()
|
156
|
+
end
|
157
|
+
|
158
|
+
##
|
159
|
+
# Change the current port speed of the server
|
160
|
+
#
|
161
|
+
# +new_speed+ is expressed Mbps and should be 0, 10, 100, or 1000.
|
162
|
+
# Ports have a maximum speed that will limit the actual speed set
|
163
|
+
# on the port.
|
164
|
+
#
|
165
|
+
# Set +public+ to +false+ in order to change the speed of the
|
166
|
+
# primary private network interface.
|
167
|
+
#
|
168
|
+
def change_port_speed(new_speed, public = true)
|
169
|
+
if public
|
170
|
+
self.service.setPublicNetworkInterfaceSpeed(new_speed)
|
171
|
+
else
|
172
|
+
self.service.setPrivateNetworkInterfaceSpeed(new_speed)
|
173
|
+
end
|
174
|
+
|
175
|
+
self.refresh_details()
|
176
|
+
self
|
177
|
+
end
|
178
|
+
|
179
|
+
##
|
180
|
+
# Begins an OS reload on this server.
|
181
|
+
#
|
182
|
+
# The OS reload can wipe out the data on your server so this method uses a
|
183
|
+
# confirmation mechanism built into the underlying SoftLayer API. If you
|
184
|
+
# call this method once without a token, it will not actually start the
|
185
|
+
# reload. Instead it will return a token to you. That token is good for
|
186
|
+
# 10 minutes. If you call this method again and pass that token **then**
|
187
|
+
# the OS reload will actually begin.
|
188
|
+
#
|
189
|
+
# If you wish to force the OS Reload and bypass the token safety mechanism
|
190
|
+
# pass the token 'FORCE' as the first parameter. If you do so
|
191
|
+
# the reload will proceed immediately.
|
192
|
+
#
|
193
|
+
def reload_os!(token = '', provisioning_script_uri = nil, ssh_keys = nil)
|
194
|
+
configuration = {}
|
195
|
+
|
196
|
+
configuration['customProvisionScriptUri'] = provisioning_script_uri if provisioning_script_uri
|
197
|
+
configuration['sshKeyIds'] = ssh_keys if ssh_keys
|
198
|
+
|
199
|
+
self.service.reloadOperatingSystem(token, configuration)
|
200
|
+
end
|
201
|
+
|
202
|
+
def to_s
|
203
|
+
result = super
|
204
|
+
if respond_to?(:hostname) then
|
205
|
+
result.sub!('>', ", #{hostname}>")
|
206
|
+
end
|
207
|
+
result
|
208
|
+
end
|
209
|
+
|
210
|
+
protected
|
211
|
+
|
212
|
+
# returns the default object mask for all servers
|
213
|
+
# structured as a hash so that the classes BareMetalServer
|
214
|
+
# and VirtualServer can use hash construction techniques to
|
215
|
+
# specialize the mask for their use.
|
216
|
+
def self.default_object_mask
|
217
|
+
{ "mask" => [
|
218
|
+
'id',
|
219
|
+
'globalIdentifier',
|
220
|
+
'notes',
|
221
|
+
'hostname',
|
222
|
+
'domain',
|
223
|
+
'fullyQualifiedDomainName',
|
224
|
+
'datacenter',
|
225
|
+
'primaryIpAddress',
|
226
|
+
'primaryBackendIpAddress',
|
227
|
+
{ 'operatingSystem' => {
|
228
|
+
'softwareLicense.softwareDescription' => ['manufacturer', 'name', 'version','referenceCode'],
|
229
|
+
'passwords' => ['username','password']
|
230
|
+
}
|
231
|
+
},
|
232
|
+
'privateNetworkOnlyFlag',
|
233
|
+
'userData',
|
234
|
+
'networkComponents.primarySubnet[id, netmask, broadcastAddress, networkIdentifier, gateway]',
|
235
|
+
'billingItem[id,recurringFee]',
|
236
|
+
'hourlyBillingFlag',
|
237
|
+
'tagReferences[id,tag[name,id]]',
|
238
|
+
'networkVlans[id,vlanNumber,networkSpace]',
|
239
|
+
'postInstallScriptUri'
|
240
|
+
]
|
241
|
+
}
|
242
|
+
end
|
243
|
+
|
244
|
+
end # class Server
|
245
|
+
end # module SoftLayer
|
data/lib/softlayer/Service.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
#
|
2
1
|
# Copyright (c) 2014 SoftLayer Technologies, Inc. All rights reserved.
|
3
2
|
#
|
4
3
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
@@ -51,7 +50,6 @@ class XMLRPC::Client
|
|
51
50
|
end
|
52
51
|
|
53
52
|
module SoftLayer
|
54
|
-
|
55
53
|
# = SoftLayer API Service
|
56
54
|
#
|
57
55
|
# Instances of this class are the runtime representation of
|
@@ -87,7 +85,7 @@ module SoftLayer
|
|
87
85
|
attr_reader :service_name
|
88
86
|
attr_reader :client
|
89
87
|
|
90
|
-
def initialize(service_name, options = {})
|
88
|
+
def initialize (service_name, options = {})
|
91
89
|
raise ArgumentError,"Please provide a service name" if service_name.nil? || service_name.empty?
|
92
90
|
|
93
91
|
# remember the service name
|
@@ -137,6 +135,13 @@ using either client.service_named('<service_name_here>') or client['<service_nam
|
|
137
135
|
@client.service_named(service_name)
|
138
136
|
end
|
139
137
|
|
138
|
+
# Added here so that the interface of this class matches that
|
139
|
+
# of APIParameterFilter. In APIParameterFilter the target is
|
140
|
+
# a service. In a service, the target is itself.
|
141
|
+
def target
|
142
|
+
return self
|
143
|
+
end
|
144
|
+
|
140
145
|
# Use this as part of a method call chain to identify a particular
|
141
146
|
# object as the target of the request. The parameter is the SoftLayer
|
142
147
|
# object identifier you are interested in. For example, this call
|
@@ -165,7 +170,7 @@ using either client.service_named('<service_name_here>') or client['<service_nam
|
|
165
170
|
# Use this as part of a method call chain to reduce the number
|
166
171
|
# of results returned from the server. For example, if the server has a list
|
167
172
|
# of 100 entities and you only want 5 of them, you can get the first five
|
168
|
-
# by using result_limit(0,5).
|
173
|
+
# by using result_limit(0,5). Then for the next 5 you would use
|
169
174
|
# result_limit(5,5), then result_limit(10,5) etc.
|
170
175
|
def result_limit(offset, limit)
|
171
176
|
proxy = APIParameterFilter.new(self)
|
@@ -234,11 +239,9 @@ using either client.service_named('<service_name_here>') or client['<service_nam
|
|
234
239
|
end
|
235
240
|
|
236
241
|
# Object masks go into the headers too.
|
237
|
-
if parameters && parameters.server_object_mask
|
242
|
+
if parameters && parameters.server_object_mask
|
238
243
|
object_mask = parameters.server_object_mask
|
239
|
-
|
240
|
-
|
241
|
-
additional_headers.merge!("SoftLayer_ObjectMask" => { "mask" => object_mask_string }) unless object_mask_string.empty?
|
244
|
+
additional_headers.merge!("SoftLayer_ObjectMask" => { "mask" => object_mask }) unless object_mask.empty?
|
242
245
|
end
|
243
246
|
|
244
247
|
# Result limits go into the headers
|
@@ -284,7 +287,7 @@ using either client.service_named('<service_name_here>') or client['<service_nam
|
|
284
287
|
# If this is not defined for Service, then when you print a service object
|
285
288
|
# the code will try to convert it to an array and end up calling method_missing
|
286
289
|
#
|
287
|
-
# We define this here to prevent odd calls to the
|
290
|
+
# We define this here to prevent odd calls to the SoftLayer API
|
288
291
|
def to_ary
|
289
292
|
nil
|
290
293
|
end
|