Skip to content

Commit 8ffe12f

Browse files
#208 quote ordering support and doc updates
1 parent cfab07e commit 8ffe12f

File tree

13 files changed

+311
-123
lines changed

13 files changed

+311
-123
lines changed

SoftLayer/CLI/order/category_list.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,11 @@
1919
def cli(env, package_keyname, required):
2020
"""List the categories of a package.
2121
22-
Package keynames can be retrieved from `slcli order package-list`
22+
::
2323
24-
\b
25-
Example:
2624
# List the categories of Bare Metal servers
2725
slcli order category-list BARE_METAL_SERVER
2826
29-
When using the --required flag, it will list out only the categories
30-
that are required for ordering that package (see `slcli order item-list`)
31-
32-
\b
33-
Example:
3427
# List the required categories for Bare Metal servers
3528
slcli order category-list BARE_METAL_SERVER --required
3629

SoftLayer/CLI/order/item_list.py

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,18 @@
1818
def cli(env, package_keyname, keyword, category):
1919
"""List package items used for ordering.
2020
21-
The items listed can be used with `slcli order place` to specify
21+
The item keyNames listed can be used with `slcli order place` to specify
2222
the items that are being ordered in the package.
2323
24-
Package keynames can be retrieved using `slcli order package-list`
25-
26-
\b
27-
Note:
24+
.. Note::
2825
Items with a numbered category, like disk0 or gpu0, can be included
2926
multiple times in an order to match how many of the item you want to order.
3027
31-
\b
32-
Example:
28+
::
29+
3330
# List all items in the VSI package
3431
slcli order item-list CLOUD_SERVER
3532
36-
The --keyword option is used to filter items by name.
37-
38-
The --category option is used to filter items by category.
39-
40-
Both --keyword and --category can be used together.
41-
42-
\b
43-
Example:
4433
# List Ubuntu OSes from the os category of the Bare Metal package
4534
slcli order item-list BARE_METAL_SERVER --category os --keyword ubuntu
4635

SoftLayer/CLI/order/package_list.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,16 @@
2020
def cli(env, keyword, package_type):
2121
"""List packages that can be ordered via the placeOrder API.
2222
23-
\b
24-
Example:
25-
# List out all packages for ordering
26-
slcli order package-list
2723
24+
::
2825
29-
Keywords can also be used for some simple filtering functionality
30-
to help find a package easier.
26+
# List out all packages for ordering
27+
slcli order package-list
3128
32-
\b
33-
Example:
3429
# List out all packages with "server" in the name
3530
slcli order package-list --keyword server
3631
37-
Package types can be used to remove unwanted packages
38-
\b
39-
Example:
32+
# Select only specifict package types
4033
slcli order package-list --package_type BARE_METAL_CPU
4134
"""
4235
manager = ordering.OrderingManager(env.client)

SoftLayer/CLI/order/place.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232
default='hourly',
3333
show_default=True,
3434
help="Billing rate")
35-
@click.option('--complex-type', help=("The complex type of the order. This typically begins"
36-
" with 'SoftLayer_Container_Product_Order_'."))
35+
@click.option('--complex-type',
36+
help=("The complex type of the order. Starts with 'SoftLayer_Container_Product_Order'."))
3737
@click.option('--extras',
3838
help="JSON string denoting extra data that needs to be sent with the order")
3939
@click.argument('order_items', nargs=-1)
@@ -55,8 +55,9 @@ def cli(env, package_keyname, location, preset, verify, billing, complex_type,
5555
items for the order, use `slcli order category-list`, and then provide the
5656
--category option for each category code in `slcli order item-list`.
5757
58-
\b
59-
Example:
58+
59+
Example::
60+
6061
# Order an hourly VSI with 4 CPU, 16 GB RAM, 100 GB SAN disk,
6162
# Ubuntu 16.04, and 1 Gbps public & private uplink in dal13
6263
slcli order place --billing hourly CLOUD_SERVER DALLAS13 \\

SoftLayer/CLI/order/place_quote.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
help="A custom name to be assigned to the quote (optional)")
2121
@click.option('--send-email',
2222
is_flag=True,
23-
help="The quote will be sent to the email address associated.")
24-
@click.option('--complex-type', help=("The complex type of the order. This typically begins"
25-
" with 'SoftLayer_Container_Product_Order_'."))
23+
help="The quote will be sent to the email address associated with your user.")
24+
@click.option('--complex-type',
25+
help="The complex type of the order. Starts with 'SoftLayer_Container_Product_Order'.")
2626
@click.option('--extras',
2727
help="JSON string denoting extra data that needs to be sent with the order")
2828
@click.argument('order_items', nargs=-1)
@@ -31,7 +31,7 @@ def cli(env, package_keyname, location, preset, name, send_email, complex_type,
3131
extras, order_items):
3232
"""Place a quote.
3333
34-
This CLI command is used for placing a quote of the specified package in
34+
This CLI command is used for creating a quote of the specified package in
3535
the given location (denoted by a datacenter's long name). Orders made via the CLI
3636
can then be converted to be made programmatically by calling
3737
SoftLayer.OrderingManager.place_quote() with the same keynames.
@@ -44,8 +44,9 @@ def cli(env, package_keyname, location, preset, name, send_email, complex_type,
4444
items for the order, use `slcli order category-list`, and then provide the
4545
--category option for each category code in `slcli order item-list`.
4646
47-
\b
48-
Example:
47+
48+
Example::
49+
4950
# Place quote a VSI with 4 CPU, 16 GB RAM, 100 GB SAN disk,
5051
# Ubuntu 16.04, and 1 Gbps public & private uplink in dal13
5152
slcli order place-quote --name "foobar" --send-email CLOUD_SERVER DALLAS13 \\

SoftLayer/CLI/order/preset_list.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,15 @@
2020
def cli(env, package_keyname, keyword):
2121
"""List package presets.
2222
23-
Package keynames can be retrieved from `slcli order package-list`.
24-
Some packages do not have presets.
23+
.. Note::
24+
Presets are set CPU / RAM / Disk allotments. You still need to specify required items.
25+
Some packages do not have presets.
26+
27+
::
2528
26-
\b
27-
Example:
2829
# List the presets for Bare Metal servers
2930
slcli order preset-list BARE_METAL_SERVER
3031
31-
The --keyword option can also be used for additional filtering on
32-
the returned presets.
33-
34-
\b
35-
Example:
3632
# List the Bare Metal server presets that include a GPU
3733
slcli order preset-list BARE_METAL_SERVER --keyword gpu
3834

SoftLayer/CLI/order/quote.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
"""View and Order a quote"""
2+
# :license: MIT, see LICENSE for more details.
3+
import click
4+
import json
5+
6+
from SoftLayer.CLI import environment
7+
from SoftLayer.CLI import exceptions
8+
from SoftLayer.CLI import formatting
9+
from SoftLayer.CLI import helpers
10+
from SoftLayer.managers import ordering
11+
from SoftLayer.utils import lookup, clean_time
12+
13+
14+
15+
from pprint import pprint as pp
16+
17+
18+
def _parse_create_args(client, args):
19+
"""Converts CLI arguments to args for VSManager.create_instance.
20+
21+
:param dict args: CLI arguments
22+
"""
23+
data = {}
24+
25+
if args.get('quantity'):
26+
data['quantity'] = int(args.get('quantity'))
27+
if args.get('postinstall'):
28+
data['provisionScripts'] = [args.get('postinstall')]
29+
if args.get('complex_type'):
30+
data['complexType'] = args.get('complex_type')
31+
32+
if args.get('fqdn'):
33+
servers = []
34+
for name in args.get('fqdn'):
35+
fqdn = name.split(".", 1)
36+
servers.append({'hostname': fqdn[0], 'domain': fqdn[1]})
37+
data['hardware'] = servers
38+
39+
if args.get('image'):
40+
if args.get('image').isdigit():
41+
image_mgr = SoftLayer.ImageManager(client)
42+
image_details = image_mgr.get_image(args.get('image'), mask="id,globalIdentifier")
43+
data['image_id'] = image_details['globalIdentifier']
44+
else:
45+
data['image_id'] = args['image']
46+
47+
if args.get('userdata'):
48+
data['userdata'] = args['userdata']
49+
elif args.get('userfile'):
50+
with open(args['userfile'], 'r') as userfile:
51+
data['userdata'] = userfile.read()
52+
53+
# Get the SSH keys
54+
if args.get('key'):
55+
keys = []
56+
for key in args.get('key'):
57+
resolver = SoftLayer.SshKeyManager(client).resolve_ids
58+
key_id = helpers.resolve_id(resolver, key, 'SshKey')
59+
keys.append(key_id)
60+
data['ssh_keys'] = keys
61+
62+
63+
return data
64+
65+
66+
@click.command()
67+
@click.argument('quote')
68+
@click.option('--verify', is_flag=True, default=False, show_default=True,
69+
help="If specified, will only show what the quote will order, will NOT place an order")
70+
@click.option('--quantity', type=int, default=None,
71+
help="The quantity of the item being ordered if different from quoted value")
72+
@click.option('--complex-type', default='SoftLayer_Container_Product_Order_Hardware_Server', show_default=True,
73+
help=("The complex type of the order. Starts with 'SoftLayer_Container_Product_Order'."))
74+
@click.option('--userdata', '-u', help="User defined metadata string")
75+
@click.option('--userfile', '-F', type=click.Path(exists=True, readable=True, resolve_path=True),
76+
help="Read userdata from file")
77+
@click.option('--postinstall', '-i', help="Post-install script to download")
78+
@helpers.multi_option('--key', '-k', help="SSH keys to add to the root user")
79+
@helpers.multi_option('--fqdn', required=True,
80+
help="<hostname>.<domain.name.tld> formatted name to use. Specify one fqdn per server")
81+
@click.option('--image', help="Image ID. See: 'slcli image list' for reference")
82+
@environment.pass_env
83+
def cli(env, quote, **args):
84+
"""View and Order a quote"""
85+
table = formatting.Table([
86+
'Id', 'Name', 'Created', 'Expiration', 'Status'
87+
])
88+
create_args = _parse_create_args(env.client, args)
89+
90+
manager = ordering.OrderingManager(env.client)
91+
quote_details = manager.get_quote_details(quote)
92+
93+
package = quote_details['order']['items'][0]['package']
94+
create_args['packageId'] = package['id']
95+
96+
if args.get('verify'):
97+
result = manager.verify_quote(quote, create_args)
98+
verify_table = formatting.Table(['keyName', 'description', 'cost'])
99+
verify_table.align['keyName'] = 'l'
100+
verify_table.align['description'] = 'l'
101+
for price in result['prices']:
102+
cost_key = 'hourlyRecurringFee' if result['useHourlyPricing'] is True else 'recurringFee'
103+
verify_table.add_row([
104+
price['item']['keyName'],
105+
price['item']['description'],
106+
price[cost_key] if cost_key in price else formatting.blank()
107+
])
108+
env.fout(verify_table)
109+
else:
110+
result = manager.order_quote(quote, create_args)
111+
table = formatting.KeyValueTable(['name', 'value'])
112+
table.align['name'] = 'r'
113+
table.align['value'] = 'l'
114+
table.add_row(['id', result['orderId']])
115+
table.add_row(['created', result['orderDate']])
116+
table.add_row(['status', result ['placedOrder']['status']])
117+
env.fout(table)
118+
119+
120+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""View a quote"""
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+
from SoftLayer.utils import lookup, clean_time
9+
10+
11+
@click.command()
12+
@click.argument('quote')
13+
@environment.pass_env
14+
def cli(env, quote):
15+
"""View a quote"""
16+
17+
manager = ordering.OrderingManager(env.client)
18+
result = manager.get_quote_details(quote)
19+
20+
package = result['order']['items'][0]['package']
21+
title = "{} - Package: {}, Id {}".format(result.get('name'), package['keyName'], package['id'])
22+
table = formatting.Table([
23+
'Category', 'Description', 'Quantity', 'Recurring', 'One Time'
24+
], title=title)
25+
table.align['Category'] = 'l'
26+
table.align['Description'] = 'l'
27+
28+
items = lookup(result, 'order', 'items')
29+
for item in items:
30+
table.add_row([
31+
item.get('categoryCode'),
32+
item.get('description'),
33+
item.get('quantity'),
34+
item.get('recurringFee'),
35+
item.get('oneTimeFee')
36+
])
37+
38+
env.fout(table)
39+
40+

SoftLayer/CLI/order/quote_list.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""List Quotes on an account."""
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+
from SoftLayer.utils import clean_time
9+
10+
from pprint import pprint as pp
11+
12+
@click.command()
13+
# @click.argument('package_keyname')
14+
@click.option('--all', is_flag=True, default=False,
15+
help="Show ALL quotes, by default only saved and pending quotes are shown")
16+
@environment.pass_env
17+
def cli(env, all):
18+
"""List all quotes on an account"""
19+
table = formatting.Table([
20+
'Id', 'Name', 'Created', 'Expiration', 'Status', 'Package Name', 'Package Id'
21+
])
22+
table.align['Name'] = 'l'
23+
table.align['Package Name'] = 'r'
24+
table.align['Package Id'] = 'l'
25+
26+
manager = ordering.OrderingManager(env.client)
27+
items = manager.get_quotes()
28+
29+
30+
for item in items:
31+
package = item['order']['items'][0]['package']
32+
table.add_row([
33+
item.get('id'),
34+
item.get('name'),
35+
clean_time(item.get('createDate')),
36+
clean_time(item.get('modifyDate')),
37+
item.get('status'),
38+
package.get('keyName'),
39+
package.get('id')
40+
])
41+
env.fout(table)
42+
43+

0 commit comments

Comments
 (0)