Skip to content

Commit b6933eb

Browse files
#828 full unit test coverage
1 parent 83266f6 commit b6933eb

File tree

4 files changed

+168
-63
lines changed

4 files changed

+168
-63
lines changed

SoftLayer/CLI/hardware/create.py

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,38 +12,25 @@
1212

1313

1414
@click.command(epilog="See 'slcli server create-options' for valid options.")
15-
@click.option('--hostname', '-H', required=True, prompt=True,
16-
help="Host portion of the FQDN")
17-
@click.option('--domain', '-D', required=True, prompt=True,
18-
help="Domain portion of the FQDN")
19-
@click.option('--size', '-s', required=True, prompt=True,
20-
help="Hardware size")
21-
@click.option('--os', '-o', required=True, prompt=True,
22-
help="OS Key value")
23-
@click.option('--datacenter', '-d', required=True, prompt=True,
24-
help="Datacenter shortname")
25-
@click.option('--port-speed', type=click.INT, required=True, prompt=True,
26-
help="Port speeds. DEPRECATED, use --network")
27-
@click.option('--no-public', is_flag=True,
28-
help="Private network only. DEPRECATED, use --network.")
29-
@click.option('--network',
30-
help="Network Option Key.")
31-
@click.option('--billing', default='hourly', show_default=True,
32-
type=click.Choice(['hourly', 'monthly']),
15+
@click.option('--hostname', '-H', required=True, prompt=True, help="Host portion of the FQDN")
16+
@click.option('--domain', '-D', required=True, prompt=True, help="Domain portion of the FQDN")
17+
@click.option('--size', '-s', required=True, prompt=True, help="Hardware size")
18+
@click.option('--os', '-o', required=True, prompt=True, help="OS Key value")
19+
@click.option('--datacenter', '-d', required=True, prompt=True, help="Datacenter shortname")
20+
@click.option('--port-speed', type=click.INT, help="Port speeds. DEPRECATED, use --network")
21+
@click.option('--no-public', is_flag=True, help="Private network only. DEPRECATED, use --network.")
22+
@click.option('--network', help="Network Option Key. Use instead of port-speed option")
23+
@click.option('--billing', default='hourly', show_default=True, type=click.Choice(['hourly', 'monthly']),
3324
help="Billing rate")
34-
@click.option('--postinstall', '-i',
35-
help="Post-install script. Should be a HTTPS URL.")
36-
@click.option('--test', is_flag=True,
37-
help="Do not actually create the server")
38-
@click.option('--template', '-t', is_eager=True,
25+
@click.option('--postinstall', '-i', help="Post-install script. Should be a HTTPS URL.")
26+
@click.option('--test', is_flag=True, help="Do not actually create the server")
27+
@click.option('--template', '-t', is_eager=True, type=click.Path(exists=True, readable=True, resolve_path=True),
3928
callback=template.TemplateCallback(list_args=['key']),
40-
help="A template file that defaults the command-line options",
41-
type=click.Path(exists=True, readable=True, resolve_path=True))
29+
help="A template file that defaults the command-line options")
4230
@click.option('--export', type=click.Path(writable=True, resolve_path=True),
4331
help="Exports options to a template file")
4432
@click.option('--wait', type=click.INT,
45-
help="Wait until the server is finished provisioning for up to "
46-
"X seconds before returning")
33+
help="Wait until the server is finished provisioning for up to X seconds before returning")
4734
@helpers.multi_option('--key', '-k', help="SSH keys to add to the root user")
4835
@helpers.multi_option('--extra', '-e', help="Extra option Key Names")
4936
@environment.pass_env
@@ -101,15 +88,13 @@ def cli(env, **args):
10188

10289
if args['export']:
10390
export_file = args.pop('export')
104-
template.export_to_template(export_file, args,
105-
exclude=['wait', 'test'])
91+
template.export_to_template(export_file, args, exclude=['wait', 'test'])
10692
env.fout('Successfully exported options to a template file.')
10793
return
10894

10995
if do_create:
11096
if not (env.skip_confirmations or formatting.confirm(
111-
"This action will incur charges on your account. "
112-
"Continue?")):
97+
"This action will incur charges on your account. Continue?")):
11398
raise exceptions.CLIAbort('Aborting dedicated server order.')
11499

115100
result = mgr.place_order(**order)

SoftLayer/managers/hardware.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -729,23 +729,23 @@ def get_hard_drives(self, instance_id):
729729
return self.hardware.getHardDrives(id=instance_id)
730730

731731

732-
def _get_extra_price_id(items, key_name, hourly, location):
733-
"""Returns a price id attached to item with the given key_name."""
732+
# def _get_extra_price_id(items, key_name, hourly, location):
733+
# """Returns a price id attached to item with the given key_name."""
734734

735-
for item in items:
736-
if utils.lookup(item, 'keyName') != key_name:
737-
continue
735+
# for item in items:
736+
# if utils.lookup(item, 'keyName') != key_name:
737+
# continue
738738

739-
for price in item['prices']:
740-
if not _matches_billing(price, hourly):
741-
continue
739+
# for price in item['prices']:
740+
# if not _matches_billing(price, hourly):
741+
# continue
742742

743-
if not _matches_location(price, location):
744-
continue
743+
# if not _matches_location(price, location):
744+
# continue
745745

746-
return price['id']
746+
# return price['id']
747747

748-
raise SoftLayerError("Could not find valid price for extra option, '%s'" % key_name)
748+
# raise SoftLayerError("Could not find valid price for extra option, '%s'" % key_name)
749749

750750

751751
def _get_bandwidth_key(items, hourly=True, no_public=False, location=None):
@@ -793,8 +793,7 @@ def _get_port_speed_key(items, port_speed, no_public, location):
793793

794794
return keyName
795795

796-
raise SoftLayerError(
797-
"Could not find valid price for port speed: '%s'" % port_speed)
796+
raise SoftLayerError("Could not find valid price for port speed: '%s'" % port_speed)
798797

799798

800799
def _matches_billing(price, hourly):

tests/CLI/modules/server_tests.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,6 @@ def test_create_options(self):
359359
self.assertEqual(output[0][0]['Value'], 'wdc01')
360360
self.assert_called_with('SoftLayer_Product_Package', 'getAllObjects')
361361

362-
363362
@mock.patch('SoftLayer.HardwareManager.place_order')
364363
def test_create_server(self, order_mock):
365364
order_mock.return_value = {
@@ -860,3 +859,27 @@ def test_billing(self):
860859
}
861860
self.assert_no_fail(result)
862861
self.assertEqual(json.loads(result.output), billing_json)
862+
863+
def test_create_hw_export(self):
864+
if(sys.platform.startswith("win")):
865+
self.skipTest("Temp files do not work properly in Windows.")
866+
with tempfile.NamedTemporaryFile() as config_file:
867+
result = self.run_command(['hw', 'create', '--hostname=test', '--export', config_file.name,
868+
'--domain=example.com', '--datacenter=TEST00',
869+
'--network=TEST_NETWORK', '--os=UBUNTU_12_64',
870+
'--size=S1270_8GB_2X1TBSATA_NORAID'])
871+
self.assert_no_fail(result)
872+
self.assertTrue('Successfully exported options to a template file.' in result.output)
873+
contents = config_file.read().decode("utf-8")
874+
self.assertIn('hostname=TEST', contents)
875+
self.assertIn('size=S1270_8GB_2X1TBSATA_NORAID', contents)
876+
877+
@mock.patch('SoftLayer.CLI.formatting.confirm')
878+
def test_create_hw_no_confirm(self, confirm_mock):
879+
confirm_mock.return_value = False
880+
881+
result = self.run_command(['hw', 'create', '--hostname=test', '--size=S1270_8GB_2X1TBSATA_NORAID',
882+
'--domain=example.com', '--datacenter=TEST00',
883+
'--network=TEST_NETWORK', '--os=UBUNTU_12_64'])
884+
885+
self.assertEqual(result.exit_code, 2)

tests/managers/hardware_tests.py

Lines changed: 115 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import copy
88

99
import mock
10-
from pprint import pprint as pp
1110

1211
import SoftLayer
1312
from SoftLayer import fixtures
@@ -118,7 +117,7 @@ def test_reload(self):
118117
def test_get_create_options(self):
119118
options = self.hardware.get_create_options()
120119

121-
extras = {'key': '1_IPV6_ADDRESS', 'name': '1 IPv6 Address'}
120+
extras = {'key': '1_IPV6_ADDRESS', 'name': '1 IPv6 Address'}
122121
locations = {'key': 'wdc01', 'name': 'Washington 1'}
123122
operating_systems = {
124123
'key': 'OS_UBUNTU_14_04_LTS_TRUSTY_TAHR_64_BIT',
@@ -141,7 +140,6 @@ def test_get_create_options(self):
141140
self.assertEqual(options['port_speeds'][0]['name'], port_speeds['name'])
142141
self.assertEqual(options['sizes'][0], sizes)
143142

144-
145143
def test_get_create_options_package_missing(self):
146144
packages = self.set_mock('SoftLayer_Product_Package', 'getAllObjects')
147145
packages.return_value = []
@@ -174,7 +172,7 @@ def test_generate_create_dict(self):
174172
'post_uri': 'http://example.com/script.php',
175173
'ssh_keys': [10],
176174
}
177-
175+
178176
package = 'BARE_METAL_SERVER'
179177
location = 'wdc01'
180178
item_keynames = [
@@ -194,7 +192,7 @@ def test_generate_create_dict(self):
194192
'hostname': 'unicorn',
195193
}],
196194
'provisionScripts': ['http://example.com/script.php'],
197-
'sshKeys' : [{'sshKeyIds': [10]}]
195+
'sshKeys': [{'sshKeyIds': [10]}]
198196
}
199197

200198
data = self.hardware._generate_create_dict(**args)
@@ -204,7 +202,25 @@ def test_generate_create_dict(self):
204202
for keyname in item_keynames:
205203
self.assertIn(keyname, data['item_keynames'])
206204
self.assertEqual(extras, data['extras'])
205+
self.assertEqual(preset_keyname, data['preset_keyname'])
206+
self.assertEqual(hourly, data['hourly'])
207207

208+
def test_generate_create_dict_network_key(self):
209+
args = {
210+
'size': 'S1270_8GB_2X1TBSATA_NORAID',
211+
'hostname': 'test1',
212+
'domain': 'test.com',
213+
'location': 'wdc01',
214+
'os': 'OS_UBUNTU_14_04_LTS_TRUSTY_TAHR_64_BIT',
215+
'network': 'NETWORKING',
216+
'hourly': True,
217+
'extras': ['1_IPV6_ADDRESS'],
218+
'post_uri': 'http://example.com/script.php',
219+
'ssh_keys': [10],
220+
}
221+
222+
data = self.hardware._generate_create_dict(**args)
223+
self.assertIn('NETWORKING', data['item_keynames'])
208224

209225
@mock.patch('SoftLayer.managers.ordering.OrderingManager.verify_order')
210226
@mock.patch('SoftLayer.managers.hardware.HardwareManager._generate_create_dict')
@@ -613,17 +629,99 @@ def test_get_hard_drive_empty(self):
613629

614630
class HardwareHelperTests(testing.TestCase):
615631

632+
def set_up(self):
633+
self.items = [
634+
{
635+
"itemCategory": {"categoryCode": "port_speed"},
636+
"capacity": 100,
637+
"attributes": [
638+
{'attributeTypeKeyName': 'NON_LACP'},
639+
{'attributeTypeKeyName': 'IS_PRIVATE_NETWORK_ONLY'}
640+
],
641+
"keyName": "ITEM_1",
642+
"prices": [{"id": 1, "locationGroupId": 100}]
643+
},
644+
{
645+
"itemCategory": {"categoryCode": "port_speed"},
646+
"capacity": 200,
647+
"attributes": [
648+
{'attributeTypeKeyName': 'YES_LACP'},
649+
{'attributeTypeKeyName': 'IS_PRIVATE_NETWORK_ONLY'}
650+
],
651+
"keyName": "ITEM_2",
652+
"prices": [{"id": 1, "locationGroupId": 151}]
653+
},
654+
{
655+
"itemCategory": {"categoryCode": "port_speed"},
656+
"capacity": 200,
657+
"attributes": [
658+
{'attributeTypeKeyName': 'YES_LACP'},
659+
{'attributeTypeKeyName': 'IS_PRIVATE_NETWORK_ONLY'}
660+
],
661+
"keyName": "ITEM_3",
662+
"prices": [{"id": 1, "locationGroupId": 51}]
663+
},
664+
{
665+
"itemCategory": {"categoryCode": "bandwidth"},
666+
"capacity": 0.0,
667+
"attributes": [],
668+
"keyName": "HOURLY_BANDWIDTH_1",
669+
"prices": [{"id": 1, "locationGroupId": 51, "hourlyRecurringFee": 1.0, "recurringFee": 1.0}]
670+
},
671+
{
672+
"itemCategory": {"categoryCode": "bandwidth"},
673+
"capacity": 10.0,
674+
"attributes": [],
675+
"keyName": "MONTHLY_BANDWIDTH_1",
676+
"prices": [{"id": 1, "locationGroupId": 151, "recurringFee": 1.0}]
677+
},
678+
{
679+
"itemCategory": {"categoryCode": "bandwidth"},
680+
"capacity": 10.0,
681+
"attributes": [],
682+
"keyName": "MONTHLY_BANDWIDTH_2",
683+
"prices": [{"id": 1, "locationGroupId": 51, "recurringFee": 1.0}]
684+
},
685+
]
686+
self.location = {'location': {'location': {'priceGroups': [{'id': 50}, {'id': 51}]}}}
687+
688+
def test_bandwidth_key(self):
689+
result = managers.hardware._get_bandwidth_key(self.items, True, False, self.location)
690+
self.assertEqual('HOURLY_BANDWIDTH_1', result)
691+
result = managers.hardware._get_bandwidth_key(self.items, False, True, self.location)
692+
self.assertEqual('HOURLY_BANDWIDTH_1', result)
693+
result = managers.hardware._get_bandwidth_key(self.items, False, False, self.location)
694+
self.assertEqual('MONTHLY_BANDWIDTH_2', result)
695+
ex = self.assertRaises(SoftLayer.SoftLayerError,
696+
managers.hardware._get_bandwidth_key, [], True, False, self.location)
697+
self.assertEqual("Could not find valid price for bandwidth option", str(ex))
698+
699+
def test_port_speed_key(self):
700+
result = managers.hardware._get_port_speed_key(self.items, 200, True, self.location)
701+
self.assertEqual("ITEM_3", result)
702+
703+
def test_port_speed_key_exception(self):
704+
items = []
705+
location = {}
706+
ex = self.assertRaises(SoftLayer.SoftLayerError,
707+
managers.hardware._get_port_speed_key, items, 999, False, location)
708+
self.assertEqual("Could not find valid price for port speed: '999'", str(ex))
709+
616710
def test_matches_location(self):
617711
price = {'id': 1, 'locationGroupId': 51, 'recurringFee': 99}
618-
location = {
619-
'location': {
620-
'location': {
621-
'priceGroups': [
622-
{'id': 50},
623-
{'id': 51}
624-
]
625-
}
626-
}
627-
}
628-
result = managers.hardware._matches_location(price, location)
629-
self.assertTrue(result)
712+
713+
self.assertTrue(managers.hardware._matches_location(price, self.location))
714+
price['locationGroupId'] = 99999
715+
self.assertFalse(managers.hardware._matches_location(price, self.location))
716+
717+
def test_is_bonded(self):
718+
item_non_lacp = {'attributes': [{'attributeTypeKeyName': 'NON_LACP'}]}
719+
item_lacp = {'attributes': [{'attributeTypeKeyName': 'YES_LACP'}]}
720+
self.assertFalse(managers.hardware._is_bonded(item_non_lacp))
721+
self.assertTrue(managers.hardware._is_bonded(item_lacp))
722+
723+
def test_is_private(self):
724+
item_private = {'attributes': [{'attributeTypeKeyName': 'IS_PRIVATE_NETWORK_ONLY'}]}
725+
item_public = {'attributes': [{'attributeTypeKeyName': 'NOT_PRIVATE_NETWORK_ONLY'}]}
726+
self.assertTrue(managers.hardware._is_private_port_speed_item(item_private))
727+
self.assertFalse(managers.hardware._is_private_port_speed_item(item_public))

0 commit comments

Comments
 (0)