diff --git a/SoftLayer/CLI/subnet/create.py b/SoftLayer/CLI/subnet/create.py index 1844cf627..5918c5859 100644 --- a/SoftLayer/CLI/subnet/create.py +++ b/SoftLayer/CLI/subnet/create.py @@ -10,25 +10,33 @@ @click.command(short_help="Add a new subnet to your account") -@click.argument('network', type=click.Choice(['public', 'private'])) +@click.argument('network', type=click.Choice(['static', 'public', 'private'])) @click.argument('quantity', type=click.INT) -@click.argument('vlan-id') +@click.argument('endpoint-id', type=click.INT) @click.option('--ipv6', '--v6', is_flag=True, help="Order IPv6 Addresses") @click.option('--test', is_flag=True, help="Do not order the subnet; just get a quote") @environment.pass_env -def cli(env, network, quantity, vlan_id, ipv6, test): +def cli(env, network, quantity, endpoint_id, ipv6, test): """Add a new subnet to your account. Valid quantities vary by type. \b - Type - Valid Quantities (IPv4) - public - 4, 8, 16, 32 - private - 4, 8, 16, 32, 64 + IPv4 + static - 1, 2, 4, 8, 16, 32, 64, 128, 256 + public - 4, 8, 16, 32, 64, 128, 256 + private - 4, 8, 16, 32, 64, 128, 256 \b - Type - Valid Quantities (IPv6) + IPv6 + static - 64 public - 64 + + \b + endpoint-id + static - Network_Subnet_IpAddress identifier. + public - Network_Vlan identifier + private - Network_Vlan identifier """ mgr = SoftLayer.NetworkManager(env.client) @@ -43,9 +51,13 @@ def cli(env, network, quantity, vlan_id, ipv6, test): version = 6 try: - result = mgr.add_subnet(network, quantity=quantity, vlan_id=vlan_id, version=version, test_order=test) - except SoftLayer.SoftLayerAPIError: - raise exceptions.CLIAbort('There is no price id for {} {} ipv{}'.format(quantity, network, version)) + result = mgr.add_subnet(network, quantity=quantity, endpoint_id=endpoint_id, version=version, test_order=test) + + except SoftLayer.SoftLayerAPIError as error: + raise exceptions.CLIAbort('Unable to order {} {} ipv{} , error: {}'.format(quantity, + network, + version, + error.faultString)) table = formatting.Table(['Item', 'cost']) table.align['Item'] = 'r' diff --git a/SoftLayer/managers/network.py b/SoftLayer/managers/network.py index 5fb25ee09..dbfb9c3f6 100644 --- a/SoftLayer/managers/network.py +++ b/SoftLayer/managers/network.py @@ -110,13 +110,13 @@ def add_securitygroup_rules(self, group_id, rules): raise TypeError("The rules provided must be a list of dictionaries") return self.security_group.addRules(rules, id=group_id) - def add_subnet(self, subnet_type, quantity=None, vlan_id=None, version=4, + def add_subnet(self, subnet_type, quantity=None, endpoint_id=None, version=4, test_order=False): """Orders a new subnet - :param str subnet_type: Type of subnet to add: private, public, global + :param str subnet_type: Type of subnet to add: private, public, global,static :param int quantity: Number of IPs in the subnet - :param int vlan_id: VLAN id for the subnet to be placed into + :param int endpoint_id: id for the subnet to be placed into :param int version: 4 for IPv4, 6 for IPv6 :param bool test_order: If true, this will only verify the order. """ @@ -126,9 +126,11 @@ def add_subnet(self, subnet_type, quantity=None, vlan_id=None, version=4, if version == 4: if subnet_type == 'global': quantity = 0 - category = 'global_ipv4' + category = "global_ipv4" elif subnet_type == 'public': - category = 'sov_sec_ip_addresses_pub' + category = "sov_sec_ip_addresses_pub" + elif subnet_type == 'static': + category = "static_sec_ip_addresses" else: category = 'static_ipv6_addresses' if subnet_type == 'global': @@ -137,6 +139,8 @@ def add_subnet(self, subnet_type, quantity=None, vlan_id=None, version=4, desc = 'Global' elif subnet_type == 'public': desc = 'Portable' + elif subnet_type == 'static': + desc = 'Static' # In the API, every non-server item is contained within package ID 0. # This means that we need to get all of the items and loop through them @@ -144,7 +148,8 @@ def add_subnet(self, subnet_type, quantity=None, vlan_id=None, version=4, # item description. price_id = None quantity_str = str(quantity) - for item in package.getItems(id=0, mask='itemCategory'): + package_items = package.getItems(id=0) + for item in package_items: category_code = utils.lookup(item, 'itemCategory', 'categoryCode') if all([category_code == category, item.get('capacity') == quantity_str, @@ -161,9 +166,10 @@ def add_subnet(self, subnet_type, quantity=None, vlan_id=None, version=4, # correct order container 'complexType': 'SoftLayer_Container_Product_Order_Network_Subnet', } - - if subnet_type != 'global': - order['endPointVlanId'] = vlan_id + if subnet_type == 'static': + order['endPointIpAddressId'] = endpoint_id + elif subnet_type != 'global' and subnet_type != 'static': + order['endPointVlanId'] = endpoint_id if test_order: return self.client['Product_Order'].verifyOrder(order) diff --git a/tests/CLI/modules/subnet_tests.py b/tests/CLI/modules/subnet_tests.py index befc6a2e7..1971aa420 100644 --- a/tests/CLI/modules/subnet_tests.py +++ b/tests/CLI/modules/subnet_tests.py @@ -94,4 +94,43 @@ def test_create_subnet_no_prices_found(self): result = self.run_command(['subnet', 'create', '--v6', 'public', '32', '12346', '--test']) self.assertRaises(SoftLayer.SoftLayerAPIError, verify_mock) - self.assertEqual(result.exception.message, 'There is no price id for 32 public ipv6') + self.assertIn('Unable to order 32 public ipv6', result.exception.message, ) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_subnet_static(self, confirm_mock): + confirm_mock.return_value = True + + item_mock = self.set_mock('SoftLayer_Product_Package', 'getItems') + item_mock.return_value = SoftLayer_Product_Package.getItems + + place_mock = self.set_mock('SoftLayer_Product_Order', 'placeOrder') + place_mock.return_value = SoftLayer_Product_Order.placeOrder + + result = self.run_command(['subnet', 'create', 'static', '2', '12346']) + self.assert_no_fail(result) + + output = [ + {'Item': 'Total monthly cost', 'cost': '0.00'} + ] + + self.assertEqual(output, json.loads(result.output)) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_subnet_static_ipv6(self, confirm_mock): + confirm_mock.return_value = True + + item_mock = self.set_mock('SoftLayer_Product_Package', 'getItems') + item_mock.return_value = SoftLayer_Product_Package.getItems + + place_mock = self.set_mock('SoftLayer_Product_Order', 'verifyOrder') + place_mock.return_value = SoftLayer_Product_Order.verifyOrder + + result = self.run_command(['subnet', 'create', '--v6', 'static', '64', '12346', '--test']) + self.assert_no_fail(result) + + output = [ + {'Item': 'this is a thing', 'cost': '2.00'}, + {'Item': 'Total monthly cost', 'cost': '2.00'} + ] + + self.assertEqual(output, json.loads(result.output)) diff --git a/tests/managers/network_tests.py b/tests/managers/network_tests.py index 812781c9b..a87441a99 100644 --- a/tests/managers/network_tests.py +++ b/tests/managers/network_tests.py @@ -81,7 +81,7 @@ def test_add_subnet_for_ipv4(self): # Test a four public address IPv4 order result = self.network.add_subnet('public', quantity=4, - vlan_id=1234, + endpoint_id=1234, version=4, test_order=True) @@ -89,7 +89,7 @@ def test_add_subnet_for_ipv4(self): result = self.network.add_subnet('public', quantity=4, - vlan_id=1234, + endpoint_id=1234, version=4, test_order=False) @@ -104,7 +104,7 @@ def test_add_subnet_for_ipv6(self): # Test a public IPv6 order result = self.network.add_subnet('public', quantity=64, - vlan_id=45678, + endpoint_id=45678, version=6, test_order=True)