softlayer_api 2.0.1 → 2.1.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/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
|