Skip to content

Commit

Permalink
Merge pull request #924 from allmightyspiff/issues918
Browse files Browse the repository at this point in the history
Add categories to item-list and package location support
  • Loading branch information
allmightyspiff committed Jan 15, 2018
2 parents e5b41ec + adc58ff commit 6e53935
Show file tree
Hide file tree
Showing 13 changed files with 192 additions and 216 deletions.
41 changes: 29 additions & 12 deletions SoftLayer/CLI/order/item_list.py
@@ -1,22 +1,19 @@
"""List package items."""
# :license: MIT, see LICENSE for more details.

import click

from SoftLayer.CLI import environment
from SoftLayer.CLI import formatting
from SoftLayer.managers import ordering
from SoftLayer.utils import lookup

COLUMNS = ['keyName',
'description', ]
COLUMNS = ['category', 'keyName', 'description']


@click.command()
@click.argument('package_keyname')
@click.option('--keyword',
help="A word (or string) used to filter item names.")
@click.option('--category',
help="Category code to filter items by")
@click.option('--keyword', help="A word (or string) used to filter item names.")
@click.option('--category', help="Category code to filter items by")
@environment.pass_env
def cli(env, package_keyname, keyword, category):
"""List package items used for ordering.
Expand All @@ -26,13 +23,20 @@ def cli(env, package_keyname, keyword, category):
Package keynames can be retrieved using `slcli order package-list`
\b
Note:
Items with a numbered category, like disk0 or gpu0, can be included
multiple times in an order to match how many of the item you want to order.
\b
Example:
# List all items in the VSI package
slcli order item-list CLOUD_SERVER
The --keyword option is used to filter items by name.
The --category option is used to filter items by category.
Both --keyword and --category can be used together.
\b
Expand All @@ -51,10 +55,23 @@ def cli(env, package_keyname, keyword, category):
_filter['items']['categories'] = {'categoryCode': {'operation': '_= %s' % category}}

items = manager.list_items(package_keyname, filter=_filter)
sorted_items = sort_items(items)

for item in items:
table.add_row([
item['keyName'],
item['description'],
])
categories = sorted_items.keys()
for catname in sorted(categories):
for item in sorted_items[catname]:
table.add_row([catname, item['keyName'], item['description']])
env.fout(table)


def sort_items(items):
"""sorts the items into a dictionary of categories, with a list of items"""

sorted_items = {}
for item in items:
category = lookup(item, 'itemCategory', 'categoryCode')
if sorted_items.get(category) is None:
sorted_items[category] = []
sorted_items[category].append(item)

return sorted_items
32 changes: 32 additions & 0 deletions SoftLayer/CLI/order/package_locations.py
@@ -0,0 +1,32 @@
"""List packages."""
# :license: MIT, see LICENSE for more details.
import click

from SoftLayer.CLI import environment
from SoftLayer.CLI import formatting
from SoftLayer.managers import ordering

COLUMNS = ['id', 'dc', 'description', 'keyName']


@click.command()
@click.argument('package_keyname')
@environment.pass_env
def cli(env, package_keyname):
"""List Datacenters a package can be ordered in.
Use the location Key Name to place orders
"""
manager = ordering.OrderingManager(env.client)
table = formatting.Table(COLUMNS)

locations = manager.package_locations(package_keyname)
for region in locations:
for datacenter in region['locations']:
table.add_row([
datacenter['location']['id'],
datacenter['location']['name'],
region['description'],
region['keyname']
])
env.fout(table)
1 change: 1 addition & 0 deletions SoftLayer/CLI/routes.py
Expand Up @@ -209,6 +209,7 @@
('order:package-list', 'SoftLayer.CLI.order.package_list:cli'),
('order:place', 'SoftLayer.CLI.order.place:cli'),
('order:preset-list', 'SoftLayer.CLI.order.preset_list:cli'),
('order:package-locations', 'SoftLayer.CLI.order.package_locations:cli'),

('rwhois', 'SoftLayer.CLI.rwhois'),
('rwhois:edit', 'SoftLayer.CLI.rwhois.edit:cli'),
Expand Down
18 changes: 18 additions & 0 deletions SoftLayer/fixtures/SoftLayer_Product_Package.py
Expand Up @@ -1121,3 +1121,21 @@
"isActive": 1,
"description": "Dedicated Host"
}]

getRegions = [{
"description": "WDC07 - Washington, DC",
"keyname": "WASHINGTON07",
"locations": [{
"location": {
"euCompliantFlag": False,
"id": 2017603,
"longName": "Washington 7",
"name": "wdc07",
"statusId": 2},
"locationPackageDetails": [{
"isAvailable": 1,
"locationId": 2017603,
"packageId": 46
}]
}]
}]
20 changes: 5 additions & 15 deletions SoftLayer/managers/dedicated_host.py
Expand Up @@ -249,12 +249,8 @@ def _get_package(self):
'''

package_keyname = 'DEDICATED_HOST'
package = self.ordering_manager.get_package_by_key(package_keyname, mask=mask)

package = self.ordering_manager.get_package_by_key(package_keyname,
mask=mask)

if package is None:
raise SoftLayer.SoftLayerError("Ordering package not found")
return package

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

raise SoftLayer.SoftLayerError("Could not find valid location for: '%s'"
% datacenter)
raise SoftLayer.SoftLayerError("Could not find valid location for: '%s'" % datacenter)

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

return {
'locations': locations,
'dedicated_host': dedicated_host,
}
return {'locations': locations, 'dedicated_host': dedicated_host}

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

raise SoftLayer.SoftLayerError(
"Could not find valid price")
raise SoftLayer.SoftLayerError("Could not find valid price")

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

raise SoftLayer.SoftLayerError("Could not find valid item for: '%s'"
% flavor)
raise SoftLayer.SoftLayerError("Could not find valid item for: '%s'" % flavor)

def _get_backend_router(self, locations, item):
"""Returns valid router options for ordering a dedicated host."""
Expand Down
30 changes: 13 additions & 17 deletions SoftLayer/managers/hardware.py
Expand Up @@ -408,25 +408,21 @@ def get_create_options(self):
def _get_package(self):
"""Get the package related to simple hardware ordering."""
mask = '''
items[
keyName,
capacity,
description,
attributes[id,attributeTypeKeyName],
itemCategory[id,categoryCode],
softwareDescription[id,referenceCode,longDescription],
prices
],
activePresets,
regions[location[location[priceGroups]]]
'''
items[
keyName,
capacity,
description,
attributes[id,attributeTypeKeyName],
itemCategory[id,categoryCode],
softwareDescription[id,referenceCode,longDescription],
prices
],
activePresets,
regions[location[location[priceGroups]]]
'''

package_keyname = 'BARE_METAL_SERVER'
package = self.ordering_manager.get_package_by_key(package_keyname,
mask=mask)
if package is None:
raise SoftLayer.SoftLayerError("Ordering package not found")

package = self.ordering_manager.get_package_by_key(package_keyname, mask=mask)
return package

def _generate_create_dict(self,
Expand Down
47 changes: 21 additions & 26 deletions SoftLayer/managers/ordering.py
Expand Up @@ -14,7 +14,7 @@
itemCategory[id, name, categoryCode]
'''

ITEM_MASK = '''id, keyName, description'''
ITEM_MASK = '''id, keyName, description, itemCategory, categories'''

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

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

container = self.generate_order_template(quote_id, extra,
quantity=quantity)
container = self.generate_order_template(quote_id, extra, quantity=quantity)
return self.order_svc.verifyOrder(container)

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

container = self.generate_order_template(quote_id, extra,
quantity=quantity)
container = self.generate_order_template(quote_id, extra, quantity=quantity)
return self.order_svc.placeOrder(container)

def get_package_by_key(self, package_keyname, mask=None):
Expand All @@ -221,17 +219,13 @@ def get_package_by_key(self, package_keyname, mask=None):
:param package_keyname: string representing the package key name we are interested in.
:param string mask: Mask to specify the properties we want to retrieve
"""
_filter = {
'keyName': {
'operation': package_keyname,
},
}
_filter = {'keyName': {'operation': package_keyname}}

packages = self.package_svc.getAllObjects(mask=mask, filter=_filter)
if len(packages) == 0:
return None
else:
return packages.pop()
raise exceptions.SoftLayerError("Package {} does not exist".format(package_keyname))

return packages.pop()

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

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

categories = self.package_svc.getConfiguration(id=package['id'], **get_kwargs)
return categories

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

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

items = self.package_svc.getItems(id=package['id'], **get_kwargs)
return items

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

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

acc_presets = self.package_svc.getAccountRestrictedActivePresets(
id=package['id'], **get_kwargs)
acc_presets = self.package_svc.getAccountRestrictedActivePresets(id=package['id'], **get_kwargs)
active_presets = self.package_svc.getActivePresets(id=package['id'], **get_kwargs)
return active_presets + acc_presets

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

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

# if there was extra data given for the order, add it to the order
# example: VSIs require hostname and domain set on the order, so
Expand All @@ -476,3 +458,16 @@ def generate_order(self, package_keyname, location, item_keynames, complex_type=
price_ids = self.get_price_id_list(package_keyname, item_keynames)
order['prices'] = [{'id': price_id} for price_id in price_ids]
return order

def package_locations(self, package_keyname):
"""List datacenter locations for a package keyname
:param str package_keyname: The package for which to get the items.
:returns: List of locations a package is orderable in
"""
mask = "mask[description, keyname, locations]"

package = self.get_package_by_key(package_keyname, mask='id')

regions = self.package_svc.getRegions(id=package['id'], mask=mask)
return regions
3 changes: 0 additions & 3 deletions SoftLayer/managers/vs.py
Expand Up @@ -852,9 +852,6 @@ def _get_package_items(self):
package_keyname = "CLOUD_SERVER"
package = self.ordering_manager.get_package_by_key(package_keyname)

if package is None:
raise ValueError("No package found for key: " + package_keyname)

package_service = self.client['Product_Package']
return package_service.getItems(id=package['id'], mask=mask)

Expand Down

0 comments on commit 6e53935

Please sign in to comment.