Skip to content

Commit 606ec64

Browse files
Merge pull request #1136 from allmightyspiff/orderingDocUpdates
Ordering doc updates - Quote ordering
2 parents f350a98 + 683af37 commit 606ec64

File tree

18 files changed

+646
-179
lines changed

18 files changed

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

SoftLayer/CLI/order/quote_list.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""List active 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+
11+
@click.command()
12+
@environment.pass_env
13+
def cli(env):
14+
"""List all active quotes on an account"""
15+
table = formatting.Table([
16+
'Id', 'Name', 'Created', 'Expiration', 'Status', 'Package Name', 'Package Id'
17+
])
18+
table.align['Name'] = 'l'
19+
table.align['Package Name'] = 'r'
20+
table.align['Package Id'] = 'l'
21+
22+
manager = ordering.OrderingManager(env.client)
23+
items = manager.get_quotes()
24+
25+
for item in items:
26+
package = item['order']['items'][0]['package']
27+
table.add_row([
28+
item.get('id'),
29+
item.get('name'),
30+
clean_time(item.get('createDate')),
31+
clean_time(item.get('modifyDate')),
32+
item.get('status'),
33+
package.get('keyName'),
34+
package.get('id')
35+
])
36+
env.fout(table)

0 commit comments

Comments
 (0)