Repository: softlayer/softlayer-python
Pull request #1149 (2019-05-24 16:54:49)

#1139 create static subnet


Patch:
diff --git a/README.rst b/README.rst
index 24b3625e..177f1514 100644
--- a/README.rst
+++ b/README.rst
@@ -31,9 +31,9 @@ http://softlayer.github.io/softlayer-python/.
 Additional API documentation can be found on the SoftLayer Development Network:
 
 * `SoftLayer API reference
-  <https://sldn.softlayer.com/reference/softlayerapi>`_
+  <http://developer.softlayer.com/reference/softlayerapi>`_
 * `Object mask information and examples
-  <https://sldn.softlayer.com/article/object-masks>`_
+  <http://developer.softlayer.com/article/Object-Masks>`_
 * `Code Examples
   <https://softlayer.github.io/python/>`_
 
diff --git a/SoftLayer/CLI/subnet/create.py b/SoftLayer/CLI/subnet/create.py
index 1844cf62..5918c585 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 5fb25ee0..dbfb9c3f 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/SoftLayer/managers/ssl.py b/SoftLayer/managers/ssl.py
index 3fa2ac1d..f0d75dc3 100644
--- a/SoftLayer/managers/ssl.py
+++ b/SoftLayer/managers/ssl.py
@@ -61,7 +61,7 @@ def add_certificate(self, certificate):
 
         :param dict certificate: A dictionary representing the parts of the
                                  certificate.
-                                 See sldn.softlayer.com for more info.
+                                 See developer.softlayer.com for more info.
 
         Example::
 
diff --git a/docs/api/client.rst b/docs/api/client.rst
index c798ac71..9fc13c1e 100644
--- a/docs/api/client.rst
+++ b/docs/api/client.rst
@@ -8,7 +8,7 @@ and executing XML-RPC calls against the SoftLayer API. Below are some links
 that will help to use the SoftLayer API.
 
 
-* `SoftLayer API Documentation <https://softlayer.github.io/reference/softlayerapi/>`_
+* `SoftLayer API Documentation <http://developer.softlayer.com/reference/softlayerapi>`_
 * `Source on GitHub <https://github.com/softlayer/softlayer-python>`_
 
 ::


Test patch:
diff --git a/tests/CLI/modules/subnet_tests.py b/tests/CLI/modules/subnet_tests.py
index befc6a2e..1971aa42 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 812781c9..a87441a9 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)