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
data/lib/softlayer/Config.rb
CHANGED
@@ -28,7 +28,7 @@ module SoftLayer
|
|
28
28
|
result = {}
|
29
29
|
result[:username] = $SL_API_USERNAME if $SL_API_USERNAME
|
30
30
|
result[:api_key] = $SL_API_KEY if $SL_API_KEY
|
31
|
-
result[:endpoint_url] = $SL_API_BASE_URL
|
31
|
+
result[:endpoint_url] = $SL_API_BASE_URL || API_PUBLIC_ENDPOINT
|
32
32
|
result
|
33
33
|
end
|
34
34
|
|
@@ -39,7 +39,7 @@ module SoftLayer
|
|
39
39
|
result
|
40
40
|
end
|
41
41
|
|
42
|
-
FILE_LOCATIONS = ['/etc/softlayer.conf', '~/.softlayer']
|
42
|
+
FILE_LOCATIONS = ['/etc/softlayer.conf', '~/.softlayer', './.softlayer']
|
43
43
|
|
44
44
|
def Config.file_settings(*additional_files)
|
45
45
|
result = {}
|
@@ -49,7 +49,6 @@ module SoftLayer
|
|
49
49
|
search_path = search_path.map { |file_path| File.expand_path(file_path) }
|
50
50
|
|
51
51
|
search_path.each do |file_path|
|
52
|
-
|
53
52
|
if File.readable? file_path
|
54
53
|
config = ConfigParser.new file_path
|
55
54
|
softlayer_section = config["softlayer"]
|
@@ -0,0 +1,170 @@
|
|
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
|
+
##
|
26
|
+
# This module is inteneded to be used by classes in the SoftLayer
|
27
|
+
# object model. It creates a small DSL for creating attributes
|
28
|
+
# that update themselves dynamically (usually by making requests
|
29
|
+
# to the SoftLayer API)
|
30
|
+
#
|
31
|
+
# +sl_dynamic_attr+ is an implementation of a memoization scheme
|
32
|
+
# The module creates a getter which is implemented in terms of a
|
33
|
+
# predicate (identifying whether or not the attribute needs to be updated) and
|
34
|
+
# an update routine
|
35
|
+
#
|
36
|
+
# When the getter is called, it checks the predicate routine to see if
|
37
|
+
# the attribute needs to be updated. If it doesn't, then the getter simply
|
38
|
+
# returns the cached value for the attribute. If the attribute does need
|
39
|
+
# to be updated, the getter calls the update routine to get a new value
|
40
|
+
# and caches that value off before returning it to the caller.
|
41
|
+
#
|
42
|
+
# Declaring a attribute adds three methods to a class and
|
43
|
+
# a corresponding instance variable in instances of the class
|
44
|
+
# All three are based on the name of the attribute:
|
45
|
+
#
|
46
|
+
# * The getter simply has the same name as the attribute
|
47
|
+
# * The predicate routine is called +should_update_<attribute name>?+
|
48
|
+
# * The updating routine is called +update_<attribute name>!+
|
49
|
+
#
|
50
|
+
# The getter can also be called with a boolean argument. If that
|
51
|
+
# argument is true, the getter will force the attribute to be updated
|
52
|
+
# without consulting the +should_update?+ predicate
|
53
|
+
#
|
54
|
+
# When a attribute is defined, the definition takes a block.
|
55
|
+
# Inside the block there is a small DSL that allows you to
|
56
|
+
# set the behavior of the +should_update?+ predicate and the +update_!+
|
57
|
+
# routine.
|
58
|
+
#
|
59
|
+
# A attribute definition might look something like this:
|
60
|
+
#
|
61
|
+
# sl_dynamic_attr :lollipop do |lollipop|
|
62
|
+
# lollipop.should_update? do
|
63
|
+
# self.lollipop_supply_is_low?
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# lollipop.to_update do
|
67
|
+
# candy_store.buy_lollipops(bakers_dozen)
|
68
|
+
# end
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
module DynamicAttribute
|
72
|
+
|
73
|
+
# The DynamicAttributeDefinition inner class is to collect and
|
74
|
+
# store information about how and when a sl_dynamic_attr
|
75
|
+
# should be updated. This class is an implementation detail
|
76
|
+
# of dynamic attributes and is not intended to be useful
|
77
|
+
# outside of that context.
|
78
|
+
class DynamicAttributeDefinition
|
79
|
+
# the name of the attribute this definition is for
|
80
|
+
attr_reader :attribute_name
|
81
|
+
|
82
|
+
# The block to call in order to update the attribute. The
|
83
|
+
# return value of this block should be the new value of the
|
84
|
+
# attribute.
|
85
|
+
attr_reader :update_block
|
86
|
+
|
87
|
+
# The block to call to see if the attribute needs to be updated.
|
88
|
+
attr_reader :should_update_block
|
89
|
+
|
90
|
+
def initialize(attribute_name)
|
91
|
+
raise ArgumentError if attribute_name.nil?
|
92
|
+
raise ArgumentError if attribute_name.to_s.empty?
|
93
|
+
|
94
|
+
@attribute_name = attribute_name;
|
95
|
+
@update_block = Proc.new { nil; };
|
96
|
+
@should_update_block = Proc.new { true; }
|
97
|
+
end
|
98
|
+
|
99
|
+
# This method is used to provide behavior for the
|
100
|
+
# should_update_ predicate for the attribute
|
101
|
+
def should_update? (&block)
|
102
|
+
@should_update_block = block
|
103
|
+
end
|
104
|
+
|
105
|
+
# This method is used to provide the behavior for
|
106
|
+
# the update_! method for the attribute.
|
107
|
+
def to_update (&block)
|
108
|
+
@update_block = block
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
module ClassMethods
|
113
|
+
# sl_dynamic_attr declares a new dynamic softlayer attribute and accepts
|
114
|
+
# a block in which the should_update? and to_update methods for the
|
115
|
+
# attribute are established.
|
116
|
+
def sl_dynamic_attr (attribute_name, &block)
|
117
|
+
attribute_definition = DynamicAttributeDefinition.new(attribute_name)
|
118
|
+
|
119
|
+
# allow the block to update the attribute definition
|
120
|
+
yield attribute_definition if block_given?
|
121
|
+
|
122
|
+
# store off the attribute definition where we can find it later
|
123
|
+
@attribute_definitions ||= {};
|
124
|
+
@attribute_definitions[attribute_name] = attribute_definition;
|
125
|
+
|
126
|
+
# define a method called "update_<attribute_name>!" which calls the update block
|
127
|
+
# stored in the attribute definition
|
128
|
+
update_symbol = "update_#{attribute_name}!".to_sym
|
129
|
+
define_method(update_symbol, &attribute_definition.update_block)
|
130
|
+
|
131
|
+
# define a method called "should_update_<attribute_name>?" which calls the
|
132
|
+
# should update block stored in the attribute definition
|
133
|
+
should_update_symbol = "should_update_#{attribute_name}?".to_sym
|
134
|
+
define_method(should_update_symbol, &attribute_definition.should_update_block)
|
135
|
+
|
136
|
+
# define an instance method of the class this is being
|
137
|
+
# called on which will get the value of the attribute.
|
138
|
+
#
|
139
|
+
# The getter will take one argument "force_update" which
|
140
|
+
# is treated as boolean value. If true, then the getter will
|
141
|
+
# force the attribute to update (by using its "to_update") block.
|
142
|
+
#
|
143
|
+
# If the force variable is false, or not given, then the
|
144
|
+
# getter will call the "should update" block to find out if the
|
145
|
+
# attribute needs to be updated.
|
146
|
+
#
|
147
|
+
getter_name = attribute_name.to_sym
|
148
|
+
value_instance_variable = "@#{attribute_name}".to_sym
|
149
|
+
|
150
|
+
define_method(getter_name) do |*args|
|
151
|
+
force_update = args[0] || false
|
152
|
+
|
153
|
+
if force_update || __send__(should_update_symbol)
|
154
|
+
instance_variable_set(value_instance_variable, __send__(update_symbol))
|
155
|
+
end
|
156
|
+
|
157
|
+
instance_variable_get(value_instance_variable)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def sl_dynamic_attr_definition(attribute_name)
|
162
|
+
@attribute_definitions[attribute_name]
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def self.included(included_in)
|
167
|
+
included_in.extend(ClassMethods)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,141 @@
|
|
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
|
+
# The SoftLayer Gem defines an Object Hierarchy representing entities in
|
26
|
+
# an account's SoftLayer environment. This class is the base object class
|
27
|
+
# for objects in that hierarchy
|
28
|
+
#
|
29
|
+
# The SoftLayer API represents entities as a hash of properties. This class
|
30
|
+
# stores that hash and allows the use of subscripting to access those properties
|
31
|
+
# directly.
|
32
|
+
#
|
33
|
+
# The class also has a model for making network requests that will refresh
|
34
|
+
# the stored hash so that it reflects the most up-to-date information about
|
35
|
+
# an entity from the server. Subclasses should override softlayer_properties
|
36
|
+
# to retrieve information from the server. Client code should call
|
37
|
+
# refresh_details to ask an object to update itself.
|
38
|
+
#
|
39
|
+
class ModelBase
|
40
|
+
# The client environment that this model object belongs to
|
41
|
+
attr_reader :softlayer_client
|
42
|
+
|
43
|
+
##
|
44
|
+
# :attr_reader: id
|
45
|
+
# The unique identifier of this object within its API service
|
46
|
+
|
47
|
+
# Construct a new model object in the environment of the given client and
|
48
|
+
# with the given hash of network data (presumably returned by the SoftLayer API)
|
49
|
+
def initialize(softlayer_client, network_hash)
|
50
|
+
raise ArgumentError, "A hash is required" if nil == network_hash
|
51
|
+
raise ArgumentError, "Model objects must be created in the context of a client" if nil == softlayer_client
|
52
|
+
|
53
|
+
@softlayer_client = softlayer_client
|
54
|
+
@softlayer_hash = network_hash
|
55
|
+
|
56
|
+
raise ArgumentError, "The hash used to construct a softlayer model object must have an id" unless has_sl_property?(:id)
|
57
|
+
raise ArgumentError, "id must be non-nil and non-empty" unless self[:id]
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# The service method of a Model object should return a SoftLayer Service
|
62
|
+
# that best represents the modeled object. For example, a Ticket models
|
63
|
+
# a particular entity in the SoftLayer_Ticket service. The particular
|
64
|
+
# entity is identified by its id so the Ticket class would return
|
65
|
+
#
|
66
|
+
# softlayer_client["Ticket"].object_with_id
|
67
|
+
#
|
68
|
+
# which is a service which would allow calls to the ticket service
|
69
|
+
# through that particular object.
|
70
|
+
def service
|
71
|
+
raise "Abstract method service in ModelBase was called"
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Asks a model object to reload itself from the SoftLayer API.
|
76
|
+
#
|
77
|
+
# Subclasses should not override this method, rather they should
|
78
|
+
# implement softlayer_properties to actually make the API request
|
79
|
+
# and return the new hash.
|
80
|
+
#
|
81
|
+
def refresh_details(object_mask = nil)
|
82
|
+
@softlayer_hash = self.softlayer_properties(object_mask)
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# Subclasses should implement this method as part of enabling the
|
87
|
+
# refresh_details fuctionality The implementation should make a request
|
88
|
+
# to the SoftLayer API and retrieve an up-to-date SoftLayer hash
|
89
|
+
# representation of this object. That hash should be the return value
|
90
|
+
# of this routine.
|
91
|
+
#
|
92
|
+
def softlayer_properties(object_mask = nil)
|
93
|
+
raise "Abstract method softlayer_properties in ModelBase was called"
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# Returns the value of of the given property as stored in the
|
98
|
+
# softlayer_hash. This gives you access to the low-level, raw
|
99
|
+
# properties that underly this model object. The need for this
|
100
|
+
# is not uncommon, but using this method should still be done
|
101
|
+
# with deliberation.
|
102
|
+
def [](softlayer_property)
|
103
|
+
self.softlayer_hash[softlayer_property.to_s]
|
104
|
+
end
|
105
|
+
|
106
|
+
##
|
107
|
+
# Returns true if the given property can be found in the softlayer hash
|
108
|
+
def has_sl_property?(softlayer_property)
|
109
|
+
softlayer_hash && softlayer_hash.has_key?(softlayer_property.to_s)
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# allows subclasses to define attributes as sl_attr
|
114
|
+
# sl_attr are attributes that draw their value from the
|
115
|
+
# low-level hash representation of the object.
|
116
|
+
def self.sl_attr(attribute_symbol, hash_key = nil)
|
117
|
+
raise "The sl_attr expects a symbol for the attribute to define" unless attribute_symbol.kind_of?(Symbol)
|
118
|
+
raise "The hash key used to define an attribute cannot be empty" if hash_key && hash_key.empty?
|
119
|
+
|
120
|
+
define_method(attribute_symbol.to_sym) { self[hash_key ? hash_key : attribute_symbol.to_s]}
|
121
|
+
end
|
122
|
+
|
123
|
+
sl_attr :id
|
124
|
+
|
125
|
+
# When printing to the console using puts, ruby will call the
|
126
|
+
# to_ary method trying to convert an object into an array of lines
|
127
|
+
# for stdio. We override to_ary to return nil for model objects
|
128
|
+
# so they may be printed
|
129
|
+
def to_ary()
|
130
|
+
return nil;
|
131
|
+
end
|
132
|
+
|
133
|
+
protected
|
134
|
+
|
135
|
+
##
|
136
|
+
# The softlayer_hash stores the low-level information about an
|
137
|
+
# object as it was retrieved from the SoftLayer API.
|
138
|
+
attr_reader :softlayer_hash
|
139
|
+
|
140
|
+
end # class ModelBase
|
141
|
+
end # module SoftLayer
|
@@ -35,9 +35,13 @@ module SoftLayer
|
|
35
35
|
'!~' # Does not Contain (case sensitive)
|
36
36
|
]
|
37
37
|
|
38
|
-
# A class whose instances represent an Object Filter
|
38
|
+
# A class whose instances represent an Object Filter operator and the value it is applied to.
|
39
39
|
class ObjectFilterOperation
|
40
|
+
|
41
|
+
# The operator, should be a member of the SoftLayer::OBJECT_FILTER_OPERATORS array
|
40
42
|
attr_reader :operator
|
43
|
+
|
44
|
+
# The operand of the operator
|
41
45
|
attr_reader :value
|
42
46
|
|
43
47
|
def initialize(operator, value)
|
@@ -49,71 +53,105 @@ module SoftLayer
|
|
49
53
|
end
|
50
54
|
|
51
55
|
def to_h
|
52
|
-
|
56
|
+
result = ObjectFilter.new
|
57
|
+
result['operation'] = "#{operator} #{value}"
|
58
|
+
|
59
|
+
result
|
53
60
|
end
|
54
61
|
end
|
55
62
|
|
56
|
-
#
|
57
|
-
# ObjectFilter.build.
|
63
|
+
# This class defines the routines that are valid within the block provided to a call to
|
64
|
+
# ObjectFilter.build. This allows you to create object filters like:
|
65
|
+
#
|
66
|
+
# object_filter = SoftLayer::ObjectFilter.build("hardware.memory") { is_greater_than(2) }
|
67
|
+
#
|
58
68
|
class ObjectFilterBlockHandler
|
59
|
-
#
|
69
|
+
# Matches when the value is found within the field
|
70
|
+
# the search is not case sensitive
|
60
71
|
def contains(value)
|
61
72
|
ObjectFilterOperation.new('*=', value)
|
62
73
|
end
|
63
74
|
|
64
|
-
#
|
75
|
+
# Matches when the value is found at the beginning of the
|
76
|
+
# field. This search is not case sensitive
|
65
77
|
def begins_with(value)
|
66
78
|
ObjectFilterOperation.new('^=', value)
|
67
79
|
end
|
68
80
|
|
69
|
-
#
|
81
|
+
# Matches when the value is found at the end of the
|
82
|
+
# field. This search is not case sensitive
|
70
83
|
def ends_with(value)
|
71
84
|
ObjectFilterOperation.new('$=', value)
|
72
85
|
end
|
73
86
|
|
74
|
-
#
|
87
|
+
# Matches when the value in the field is exactly equal to the
|
88
|
+
# given value. This is a case-sensitive match
|
75
89
|
def is(value)
|
76
90
|
ObjectFilterOperation.new('_=', value)
|
77
91
|
end
|
78
92
|
|
93
|
+
# Matches is the value in the field does not exactly equal
|
94
|
+
# the value passed in.
|
79
95
|
def is_not(value)
|
80
96
|
ObjectFilterOperation.new('!=', value)
|
81
97
|
end
|
82
98
|
|
99
|
+
# Matches when the value in the field is greater than the given value
|
83
100
|
def is_greater_than(value)
|
84
101
|
ObjectFilterOperation.new('>', value)
|
85
102
|
end
|
86
103
|
|
104
|
+
# Matches when the value in the field is less than the given value
|
87
105
|
def is_less_than(value)
|
88
106
|
ObjectFilterOperation.new('<', value)
|
89
107
|
end
|
90
108
|
|
109
|
+
# Matches when the value in the field is greater than or equal to the given value
|
91
110
|
def is_greater_or_equal_to(value)
|
92
111
|
ObjectFilterOperation.new('>=', value)
|
93
112
|
end
|
94
113
|
|
114
|
+
# Matches when the value in the field is less than or equal to the given value
|
95
115
|
def is_less_or_equal_to(value)
|
96
116
|
ObjectFilterOperation.new('<=', value)
|
97
117
|
end
|
98
118
|
|
119
|
+
# Matches when the value is found within the field
|
120
|
+
# the search _is_ case sensitive
|
99
121
|
def contains_exactly(value)
|
100
122
|
ObjectFilterOperation.new('~', value)
|
101
123
|
end
|
102
124
|
|
125
|
+
# Matches when the value is not found within the field
|
126
|
+
# the search _is_ case sensitive
|
103
127
|
def does_not_contain(value)
|
104
128
|
ObjectFilterOperation.new('!~', value)
|
105
129
|
end
|
106
130
|
end
|
107
131
|
|
108
|
-
#
|
132
|
+
#
|
133
|
+
# An ObjectFilter is a tool that, when passed to the SoftLayer API
|
134
|
+
# allows the API server to filter, or limit the result set for a call.
|
135
|
+
#
|
136
|
+
# Constructing ObjectFilters is an art that is currently somewhat
|
137
|
+
# arcane. This class tries to simplify filtering for the fundamental
|
138
|
+
# cases, while still allowing for more complex ObjectFilters to be
|
139
|
+
# created.
|
140
|
+
#
|
141
|
+
# The ObjectFilter class is implemented as a hash that, when asked to provide
|
109
142
|
# an value for an unknown key, will create a sub element
|
110
|
-
# at that key
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
143
|
+
# at that key which is, itself, an object filter. This allows you to build
|
144
|
+
# up object filters by chaining [] dereference operations.
|
145
|
+
#
|
146
|
+
# Starting empty object filter when you ask for +object_filter["foo"]+
|
147
|
+
# either the value at that hash location will be returned, or a new +foo+ key
|
148
|
+
# will be *added* to the object. The value of that key will be an +ObjectFilter+
|
149
|
+
# and that +ObjectFilter+ will be returned.
|
114
150
|
#
|
115
|
-
#
|
116
|
-
#
|
151
|
+
# By way of an example of chaining together +[]+ calls:
|
152
|
+
# object_filter["foo"]["bar"]["baz"] = 3
|
153
|
+
# yields an object filter like this:
|
154
|
+
# {"foo" => { "bar" => {"baz" => 3}}}
|
117
155
|
#
|
118
156
|
class ObjectFilter < Hash
|
119
157
|
# The default initialize for a hash is overridden
|
@@ -146,7 +184,7 @@ module SoftLayer
|
|
146
184
|
end
|
147
185
|
|
148
186
|
# if there is a block, then the query will come from
|
149
|
-
# calling the block.
|
187
|
+
# calling the block. We warn in debug mode if you override a
|
150
188
|
# query that was passed directly with the value from a block.
|
151
189
|
if block
|
152
190
|
$stderr.puts "The query from the block passed to ObjectFilter:build will override the query passed as a parameter" if $DEBUG && query
|
@@ -154,7 +192,7 @@ module SoftLayer
|
|
154
192
|
query = block_handler.instance_eval(&block)
|
155
193
|
end
|
156
194
|
|
157
|
-
# If we have a query, we assign
|
195
|
+
# If we have a query, we assign its value to the last key
|
158
196
|
# otherwise, we build an emtpy filter at the bottom
|
159
197
|
if query
|
160
198
|
case
|
@@ -176,9 +214,9 @@ module SoftLayer
|
|
176
214
|
result
|
177
215
|
end
|
178
216
|
|
179
|
-
# This method
|
180
|
-
# by
|
181
|
-
#
|
217
|
+
# This method simplifies creating correct object filter structures
|
218
|
+
# by defining a simple query language. It translates strings in that
|
219
|
+
# language into an Object Filter operations
|
182
220
|
#
|
183
221
|
# Object Filter comparisons are done using operators. Some operators make
|
184
222
|
# case sensitive comparisons and some do not. The general form of an Object
|
@@ -187,13 +225,15 @@ module SoftLayer
|
|
187
225
|
# "*= smaug"
|
188
226
|
#
|
189
227
|
# The query language also accepts some aliases using asterisks
|
190
|
-
# in a regular-expression-like way.
|
228
|
+
# in a regular-expression-like way. Those aliases look like:
|
191
229
|
#
|
192
230
|
# 'value' Exact value match (translates to '_= value')
|
193
231
|
# 'value*' Begins with value (translates to '^= value')
|
194
232
|
# '*value' Ends with value (translates to '$= value')
|
195
233
|
# '*value*' Contains value (translates to '*= value')
|
196
234
|
#
|
235
|
+
# This method corresponds to the +query_filter+ method in the SoftLayer-Python
|
236
|
+
# API.
|
197
237
|
def self.query_to_filter_operation(query)
|
198
238
|
if query.kind_of? String then
|
199
239
|
query.strip!
|