@@ -80,32 +80,75 @@ class ProductPackage < ModelBase
8080 # Run though the categories and for each one that's in our config, create a SoftLayer::ProductItemCategory object.
8181 # Conveniently the +keys+ of the required_by_category_code gives us a list of the category codes in the configuration
8282 config_categories = required_by_category_code . keys
83- categories_data . collect do |category_data |
83+
84+ # collect all the categories into an array
85+ @categories = categories_data . collect do |category_data |
8486 if config_categories . include? category_data [ 'categoryCode' ]
8587 SoftLayer ::ProductItemCategory . new ( softlayer_client , category_data , required_by_category_code [ category_data [ 'categoryCode' ] ] )
8688 else
87- nil
89+ SoftLayer :: ProductItemCategory . new ( softlayer_client , category_data , false )
8890 end
8991 end . compact
92+
93+ # The configuration consists of only those categories that are required.
94+ @categories . select { |category | category . required? }
95+ end # to_update
96+ end # configuration
97+
98+ ##
99+ # The full set of product categories contained in the package
100+ #
101+ sl_dynamic_attr :categories do |resource |
102+ resource . should_update? do
103+ @categories == nil
104+ end
105+
106+ resource . to_update do
107+ # This is a bit ugly, but what we do is ask for the configuration
108+ # which updates all the categories for the package (and marks those
109+ # that are required)
110+ self . configuration
111+
112+ # return the value constructed by the configuraiton
113+ @categories
90114 end
91115 end
92116
93117 ##
94118 # Returns an array of the required categories in this package
95119 def required_categories
96- configuration . select { | category | category . required? }
120+ configuration
97121 end
98122
99123 ##
100124 # Returns the product category with the given category code (or nil if one cannot be found)
101125 def category ( category_code )
102- configuration . find { |category | category . categoryCode == category_code }
126+ categories . find { |category | category . categoryCode == category_code }
103127 end
104128
129+ ##
130+ # Returns a list of the datacenters that this package is available in
105131 def datacenter_options
106132 available_locations . collect { |location_data | Datacenter ::datacenter_named ( location_data [ "location" ] [ "name" ] , self . softlayer_client ) } . compact
107133 end
108134
135+ ##
136+ # Returns the package items with the given description
137+ # Currently this is returning the low-level hash representation directly from the Network API
138+ #
139+ def items_with_description ( expected_description )
140+ filter = ObjectFilter . new { |filter | filter . accept ( "items.description" ) . when_it is ( expected_description ) }
141+ items_data = self . service . object_filter ( filter ) . getItems ( )
142+
143+ items_data . collect do |item_data |
144+ first_price = item_data [ 'prices' ] [ 0 ]
145+ ProductConfigurationOption . new ( item_data , first_price )
146+ end
147+ end
148+
149+ ##
150+ # Returns the service for interacting with this package through the network API
151+ #
109152 def service
110153 softlayer_client [ 'Product_Package' ] . object_with_id ( self . id )
111154 end
@@ -168,6 +211,13 @@ def self.bare_metal_server_packages(client = nil)
168211 packages_with_key_name ( 'BARE_METAL_CPU' , client )
169212 end
170213
214+ ##
215+ # The "Additional Products" package is a grab-bag of products
216+ # and services. It has a "well known" id of 0
217+ def self . additional_products_package ( client = nil )
218+ return package_with_id ( 0 , client )
219+ end
220+
171221 protected
172222
173223 def self . default_object_mask ( root )
0 commit comments