Skip to content

Commit 6e53935

Browse files
Merge pull request #924 from allmightyspiff/issues918
Add categories to item-list and package location support
2 parents e5b41ec + adc58ff commit 6e53935

File tree

13 files changed

+192
-216
lines changed

13 files changed

+192
-216
lines changed

SoftLayer/CLI/order/item_list.py

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
"""List package items."""
22
# :license: MIT, see LICENSE for more details.
3-
43
import click
54

65
from SoftLayer.CLI import environment
76
from SoftLayer.CLI import formatting
87
from SoftLayer.managers import ordering
8+
from SoftLayer.utils import lookup
99

10-
COLUMNS = ['keyName',
11-
'description', ]
10+
COLUMNS = ['category', 'keyName', 'description']
1211

1312

1413
@click.command()
1514
@click.argument('package_keyname')
16-
@click.option('--keyword',
17-
help="A word (or string) used to filter item names.")
18-
@click.option('--category',
19-
help="Category code to filter items by")
15+
@click.option('--keyword', help="A word (or string) used to filter item names.")
16+
@click.option('--category', help="Category code to filter items by")
2017
@environment.pass_env
2118
def cli(env, package_keyname, keyword, category):
2219
"""List package items used for ordering.
@@ -26,13 +23,20 @@ def cli(env, package_keyname, keyword, category):
2623
2724
Package keynames can be retrieved using `slcli order package-list`
2825
26+
\b
27+
Note:
28+
Items with a numbered category, like disk0 or gpu0, can be included
29+
multiple times in an order to match how many of the item you want to order.
30+
2931
\b
3032
Example:
3133
# List all items in the VSI package
3234
slcli order item-list CLOUD_SERVER
3335
3436
The --keyword option is used to filter items by name.
37+
3538
The --category option is used to filter items by category.
39+
3640
Both --keyword and --category can be used together.
3741
3842
\b
@@ -51,10 +55,23 @@ def cli(env, package_keyname, keyword, category):
5155
_filter['items']['categories'] = {'categoryCode': {'operation': '_= %s' % category}}
5256

5357
items = manager.list_items(package_keyname, filter=_filter)
58+
sorted_items = sort_items(items)
5459

55-
for item in items:
56-
table.add_row([
57-
item['keyName'],
58-
item['description'],
59-
])
60+
categories = sorted_items.keys()
61+
for catname in sorted(categories):
62+
for item in sorted_items[catname]:
63+
table.add_row([catname, item['keyName'], item['description']])
6064
env.fout(table)
65+
66+
67+
def sort_items(items):
68+
"""sorts the items into a dictionary of categories, with a list of items"""
69+
70+
sorted_items = {}
71+
for item in items:
72+
category = lookup(item, 'itemCategory', 'categoryCode')
73+
if sorted_items.get(category) is None:
74+
sorted_items[category] = []
75+
sorted_items[category].append(item)
76+
77+
return sorted_items
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"""List packages."""
2+
# :license: MIT, see LICENSE for more details.
3+
import click
4+
5+
from SoftLayer.CLI import environment
6+
from SoftLayer.CLI import formatting
7+
from SoftLayer.managers import ordering
8+
9+
COLUMNS = ['id', 'dc', 'description', 'keyName']
10+
11+
12+
@click.command()
13+
@click.argument('package_keyname')
14+
@environment.pass_env
15+
def cli(env, package_keyname):
16+
"""List Datacenters a package can be ordered in.
17+
18+
Use the location Key Name to place orders
19+
"""
20+
manager = ordering.OrderingManager(env.client)
21+
table = formatting.Table(COLUMNS)
22+
23+
locations = manager.package_locations(package_keyname)
24+
for region in locations:
25+
for datacenter in region['locations']:
26+
table.add_row([
27+
datacenter['location']['id'],
28+
datacenter['location']['name'],
29+
region['description'],
30+
region['keyname']
31+
])
32+
env.fout(table)

SoftLayer/CLI/routes.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@
209209
('order:package-list', 'SoftLayer.CLI.order.package_list:cli'),
210210
('order:place', 'SoftLayer.CLI.order.place:cli'),
211211
('order:preset-list', 'SoftLayer.CLI.order.preset_list:cli'),
212+
('order:package-locations', 'SoftLayer.CLI.order.package_locations:cli'),
212213

213214
('rwhois', 'SoftLayer.CLI.rwhois'),
214215
('rwhois:edit', 'SoftLayer.CLI.rwhois.edit:cli'),

SoftLayer/fixtures/SoftLayer_Product_Package.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,3 +1121,21 @@
11211121
"isActive": 1,
11221122
"description": "Dedicated Host"
11231123
}]
1124+
1125+
getRegions = [{
1126+
"description": "WDC07 - Washington, DC",
1127+
"keyname": "WASHINGTON07",
1128+
"locations": [{
1129+
"location": {
1130+
"euCompliantFlag": False,
1131+
"id": 2017603,
1132+
"longName": "Washington 7",
1133+
"name": "wdc07",
1134+
"statusId": 2},
1135+
"locationPackageDetails": [{
1136+
"isAvailable": 1,
1137+
"locationId": 2017603,
1138+
"packageId": 46
1139+
}]
1140+
}]
1141+
}]

SoftLayer/managers/dedicated_host.py

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -249,12 +249,8 @@ def _get_package(self):
249249
'''
250250

251251
package_keyname = 'DEDICATED_HOST'
252+
package = self.ordering_manager.get_package_by_key(package_keyname, mask=mask)
252253

253-
package = self.ordering_manager.get_package_by_key(package_keyname,
254-
mask=mask)
255-
256-
if package is None:
257-
raise SoftLayer.SoftLayerError("Ordering package not found")
258254
return package
259255

260256
def _get_location(self, regions, datacenter):
@@ -264,8 +260,7 @@ def _get_location(self, regions, datacenter):
264260
if region['location']['location']['name'] == datacenter:
265261
return region
266262

267-
raise SoftLayer.SoftLayerError("Could not find valid location for: '%s'"
268-
% datacenter)
263+
raise SoftLayer.SoftLayerError("Could not find valid location for: '%s'" % datacenter)
269264

270265
def get_create_options(self):
271266
"""Returns valid options for ordering a dedicated host."""
@@ -287,10 +282,7 @@ def get_create_options(self):
287282
'key': item['keyName'],
288283
})
289284

290-
return {
291-
'locations': locations,
292-
'dedicated_host': dedicated_host,
293-
}
285+
return {'locations': locations, 'dedicated_host': dedicated_host}
294286

295287
def _get_price(self, package):
296288
"""Returns valid price for ordering a dedicated host."""
@@ -299,8 +291,7 @@ def _get_price(self, package):
299291
if not price.get('locationGroupId'):
300292
return price['id']
301293

302-
raise SoftLayer.SoftLayerError(
303-
"Could not find valid price")
294+
raise SoftLayer.SoftLayerError("Could not find valid price")
304295

305296
def _get_item(self, package, flavor):
306297
"""Returns the item for ordering a dedicated host."""
@@ -309,8 +300,7 @@ def _get_item(self, package, flavor):
309300
if item['keyName'] == flavor:
310301
return item
311302

312-
raise SoftLayer.SoftLayerError("Could not find valid item for: '%s'"
313-
% flavor)
303+
raise SoftLayer.SoftLayerError("Could not find valid item for: '%s'" % flavor)
314304

315305
def _get_backend_router(self, locations, item):
316306
"""Returns valid router options for ordering a dedicated host."""

SoftLayer/managers/hardware.py

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -408,25 +408,21 @@ def get_create_options(self):
408408
def _get_package(self):
409409
"""Get the package related to simple hardware ordering."""
410410
mask = '''
411-
items[
412-
keyName,
413-
capacity,
414-
description,
415-
attributes[id,attributeTypeKeyName],
416-
itemCategory[id,categoryCode],
417-
softwareDescription[id,referenceCode,longDescription],
418-
prices
419-
],
420-
activePresets,
421-
regions[location[location[priceGroups]]]
422-
'''
411+
items[
412+
keyName,
413+
capacity,
414+
description,
415+
attributes[id,attributeTypeKeyName],
416+
itemCategory[id,categoryCode],
417+
softwareDescription[id,referenceCode,longDescription],
418+
prices
419+
],
420+
activePresets,
421+
regions[location[location[priceGroups]]]
422+
'''
423423

424424
package_keyname = 'BARE_METAL_SERVER'
425-
package = self.ordering_manager.get_package_by_key(package_keyname,
426-
mask=mask)
427-
if package is None:
428-
raise SoftLayer.SoftLayerError("Ordering package not found")
429-
425+
package = self.ordering_manager.get_package_by_key(package_keyname, mask=mask)
430426
return package
431427

432428
def _generate_create_dict(self,

SoftLayer/managers/ordering.py

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
itemCategory[id, name, categoryCode]
1515
'''
1616

17-
ITEM_MASK = '''id, keyName, description'''
17+
ITEM_MASK = '''id, keyName, description, itemCategory, categories'''
1818

1919
PACKAGE_MASK = '''id, name, keyName, isActive'''
2020

@@ -196,8 +196,7 @@ def verify_quote(self, quote_id, extra, quantity=1):
196196
:param int quantity: Quantity to override default
197197
"""
198198

199-
container = self.generate_order_template(quote_id, extra,
200-
quantity=quantity)
199+
container = self.generate_order_template(quote_id, extra, quantity=quantity)
201200
return self.order_svc.verifyOrder(container)
202201

203202
def order_quote(self, quote_id, extra, quantity=1):
@@ -209,8 +208,7 @@ def order_quote(self, quote_id, extra, quantity=1):
209208
:param int quantity: Quantity to override default
210209
"""
211210

212-
container = self.generate_order_template(quote_id, extra,
213-
quantity=quantity)
211+
container = self.generate_order_template(quote_id, extra, quantity=quantity)
214212
return self.order_svc.placeOrder(container)
215213

216214
def get_package_by_key(self, package_keyname, mask=None):
@@ -221,17 +219,13 @@ def get_package_by_key(self, package_keyname, mask=None):
221219
:param package_keyname: string representing the package key name we are interested in.
222220
:param string mask: Mask to specify the properties we want to retrieve
223221
"""
224-
_filter = {
225-
'keyName': {
226-
'operation': package_keyname,
227-
},
228-
}
222+
_filter = {'keyName': {'operation': package_keyname}}
229223

230224
packages = self.package_svc.getAllObjects(mask=mask, filter=_filter)
231225
if len(packages) == 0:
232-
return None
233-
else:
234-
return packages.pop()
226+
raise exceptions.SoftLayerError("Package {} does not exist".format(package_keyname))
227+
228+
return packages.pop()
235229

236230
def list_categories(self, package_keyname, **kwargs):
237231
"""List the categories for the given package.
@@ -246,9 +240,6 @@ def list_categories(self, package_keyname, **kwargs):
246240
get_kwargs['filter'] = kwargs['filter']
247241

248242
package = self.get_package_by_key(package_keyname, mask='id')
249-
if not package:
250-
raise exceptions.SoftLayerError("Package {} does not exist".format(package_keyname))
251-
252243
categories = self.package_svc.getConfiguration(id=package['id'], **get_kwargs)
253244
return categories
254245

@@ -266,9 +257,6 @@ def list_items(self, package_keyname, **kwargs):
266257
get_kwargs['filter'] = kwargs['filter']
267258

268259
package = self.get_package_by_key(package_keyname, mask='id')
269-
if not package:
270-
raise exceptions.SoftLayerError("Package {} does not exist".format(package_keyname))
271-
272260
items = self.package_svc.getItems(id=package['id'], **get_kwargs)
273261
return items
274262

@@ -302,11 +290,7 @@ def list_presets(self, package_keyname, **kwargs):
302290
get_kwargs['filter'] = kwargs['filter']
303291

304292
package = self.get_package_by_key(package_keyname, mask='id')
305-
if not package:
306-
raise exceptions.SoftLayerError("Package {} does not exist".format(package_keyname))
307-
308-
acc_presets = self.package_svc.getAccountRestrictedActivePresets(
309-
id=package['id'], **get_kwargs)
293+
acc_presets = self.package_svc.getAccountRestrictedActivePresets(id=package['id'], **get_kwargs)
310294
active_presets = self.package_svc.getActivePresets(id=package['id'], **get_kwargs)
311295
return active_presets + acc_presets
312296

@@ -452,8 +436,6 @@ def generate_order(self, package_keyname, location, item_keynames, complex_type=
452436
extras = extras or {}
453437

454438
package = self.get_package_by_key(package_keyname, mask='id')
455-
if not package:
456-
raise exceptions.SoftLayerError("Package {} does not exist".format(package_keyname))
457439

458440
# if there was extra data given for the order, add it to the order
459441
# example: VSIs require hostname and domain set on the order, so
@@ -476,3 +458,16 @@ def generate_order(self, package_keyname, location, item_keynames, complex_type=
476458
price_ids = self.get_price_id_list(package_keyname, item_keynames)
477459
order['prices'] = [{'id': price_id} for price_id in price_ids]
478460
return order
461+
462+
def package_locations(self, package_keyname):
463+
"""List datacenter locations for a package keyname
464+
465+
:param str package_keyname: The package for which to get the items.
466+
:returns: List of locations a package is orderable in
467+
"""
468+
mask = "mask[description, keyname, locations]"
469+
470+
package = self.get_package_by_key(package_keyname, mask='id')
471+
472+
regions = self.package_svc.getRegions(id=package['id'], mask=mask)
473+
return regions

SoftLayer/managers/vs.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -852,9 +852,6 @@ def _get_package_items(self):
852852
package_keyname = "CLOUD_SERVER"
853853
package = self.ordering_manager.get_package_by_key(package_keyname)
854854

855-
if package is None:
856-
raise ValueError("No package found for key: " + package_keyname)
857-
858855
package_service = self.client['Product_Package']
859856
return package_service.getItems(id=package['id'], mask=mask)
860857

0 commit comments

Comments
 (0)