Repository: softlayer/softlayer-python
Pull request #1287 (2020-06-20 00:09:41)

new feature edit ip note and add ipAddress table in detail
https://github.com/softlayer/softlayer-python/issues/1284


Patch:
diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py
index 60484114..92f52b68 100644
--- a/SoftLayer/CLI/routes.py
+++ b/SoftLayer/CLI/routes.py
@@ -289,6 +289,7 @@
     ('subnet:detail', 'SoftLayer.CLI.subnet.detail:cli'),
     ('subnet:list', 'SoftLayer.CLI.subnet.list:cli'),
     ('subnet:lookup', 'SoftLayer.CLI.subnet.lookup:cli'),
+    ('subnet:edit-ip', 'SoftLayer.CLI.subnet.edit_ip:cli'),
 
     ('tags', 'SoftLayer.CLI.tags'),
     ('tags:cleanup', 'SoftLayer.CLI.tags.cleanup:cli'),
diff --git a/SoftLayer/CLI/subnet/detail.py b/SoftLayer/CLI/subnet/detail.py
index 1c8f7e2d..da4b3626 100644
--- a/SoftLayer/CLI/subnet/detail.py
+++ b/SoftLayer/CLI/subnet/detail.py
@@ -25,7 +25,10 @@ def cli(env, identifier, no_vs, no_hardware):
     mgr = SoftLayer.NetworkManager(env.client)
     subnet_id = helpers.resolve_id(mgr.resolve_subnet_ids, identifier,
                                    name='subnet')
-    subnet = mgr.get_subnet(subnet_id)
+
+    mask = 'mask[ipAddresses[id, ipAddress,note], datacenter, virtualGuests, hardware]'
+
+    subnet = mgr.get_subnet(subnet_id, mask=mask)
 
     table = formatting.KeyValueTable(['name', 'value'])
     table.align['name'] = 'r'
@@ -45,6 +48,14 @@ def cli(env, identifier, no_vs, no_hardware):
     table.add_row(['usable ips',
                    subnet.get('usableIpAddressCount', formatting.blank())])
 
+    ip_address = subnet.get('ipAddresses')
+
+    ip_table = formatting.KeyValueTable(['id', 'ip', 'note'])
+    for address in ip_address:
+        ip_table.add_row([address.get('id'), address.get('ipAddress'), address.get('note')])
+
+    table.add_row(['ipAddresses', ip_table])
+
     if not no_vs:
         if subnet['virtualGuests']:
             vs_table = formatting.Table(['hostname', 'domain', 'public_ip', 'private_ip'])
diff --git a/SoftLayer/CLI/subnet/edit_ip.py b/SoftLayer/CLI/subnet/edit_ip.py
new file mode 100644
index 00000000..954b05fc
--- /dev/null
+++ b/SoftLayer/CLI/subnet/edit_ip.py
@@ -0,0 +1,27 @@
+"""Edit ip note"""
+# :license: MIT, see LICENSE for more details.
+
+import click
+
+import SoftLayer
+from SoftLayer.CLI import environment
+
+
+@click.command()
+@click.argument('identifier')
+@click.option('--note', help="set ip address note of subnet")
+@environment.pass_env
+def cli(env, identifier, note):
+    """Set the note of the ipAddress"""
+
+    data = {
+        'note': note
+    }
+    mgr = SoftLayer.NetworkManager(env.client)
+    ip_id = None
+    if str.isdigit(identifier):
+        ip_id = identifier
+    else:
+        ip_object = mgr.get_ip_by_address(identifier)
+        ip_id = ip_object.get('id')
+    mgr.set_subnet_ipddress_note(ip_id, data)
diff --git a/SoftLayer/fixtures/SoftLayer_Network_Subnet.py b/SoftLayer/fixtures/SoftLayer_Network_Subnet.py
index 7fc1e34d..c6658165 100644
--- a/SoftLayer/fixtures/SoftLayer_Network_Subnet.py
+++ b/SoftLayer/fixtures/SoftLayer_Network_Subnet.py
@@ -25,5 +25,10 @@
         }
     ],
     'hardware': [],
-    'usableIpAddressCount': 22
+    'usableIpAddressCount': 22,
+    'ipAddresses': [
+        {'id': 123456,
+         'ipAddress': '16.26.26.25'},
+        {'id': 123457,
+         'ipAddress': '16.26.26.26'}]
 }
diff --git a/SoftLayer/fixtures/SoftLayer_Network_Subnet_IpAddress.py b/SoftLayer/fixtures/SoftLayer_Network_Subnet_IpAddress.py
index d7ed9749..15778d23 100644
--- a/SoftLayer/fixtures/SoftLayer_Network_Subnet_IpAddress.py
+++ b/SoftLayer/fixtures/SoftLayer_Network_Subnet_IpAddress.py
@@ -7,3 +7,5 @@
     'isReserved': False,
     'subnetId': 5678,
 }
+
+editObject = True
diff --git a/SoftLayer/managers/network.py b/SoftLayer/managers/network.py
index b3f6f7b6..e421bd0f 100644
--- a/SoftLayer/managers/network.py
+++ b/SoftLayer/managers/network.py
@@ -727,3 +727,19 @@ def set_tags(self, tags, vlan_id):
         Just calls vlan.setTags, but if it fails from an APIError will retry.
         """
         self.vlan.setTags(tags, id=vlan_id)
+
+    def get_ip_by_address(self, ip_address):
+        """get the ip address object
+
+         :param string ip_address: the ip address to edit.
+         """
+        return self.client.call('SoftLayer_Network_Subnet_IpAddress', 'getByIpAddress', ip_address)
+
+    def set_subnet_ipddress_note(self, identifier, note):
+        """Set the ip address note of the subnet
+
+         :param integer identifier: the ip address ID to edit.
+          :param json note: the note to edit.
+        """
+        result = self.client.call('SoftLayer_Network_Subnet_IpAddress', 'editObject', note, id=identifier)
+        return result
diff --git a/docs/cli/subnet.rst b/docs/cli/subnet.rst
index 20fce0de..124f36cd 100644
--- a/docs/cli/subnet.rst
+++ b/docs/cli/subnet.rst
@@ -22,3 +22,7 @@ Subnets
 .. click:: SoftLayer.CLI.subnet.lookup:cli
     :prog: subnet lookup
     :show-nested:
+
+.. click:: SoftLayer.CLI.subnet.edit_ip:cli
+    :prog: subnet edit-ip
+    :show-nested:


Test patch:
diff --git a/tests/CLI/modules/subnet_tests.py b/tests/CLI/modules/subnet_tests.py
index 1971aa42..48d3b0a9 100644
--- a/tests/CLI/modules/subnet_tests.py
+++ b/tests/CLI/modules/subnet_tests.py
@@ -36,6 +36,9 @@ def test_detail(self):
                         'private_ip': '10.0.1.2'
                     }
                 ],
+                'ipAddresses': {
+                    '123456': '16.26.26.25',
+                    '123457': '16.26.26.26'},
                 'hardware': 'none',
                 'usable ips': 22
             },
@@ -134,3 +137,13 @@ def test_create_subnet_static_ipv6(self, confirm_mock):
         ]
 
         self.assertEqual(output, json.loads(result.output))
+
+    def test_editrou_Ip(self):
+        result = self.run_command(['subnet', 'edit-ip', '16.26.26.26', '--note=test'])
+        self.assert_no_fail(result)
+        self.assertTrue(result)
+
+    def test_editrou_Id(self):
+        result = self.run_command(['subnet', 'edit-ip', '123456', '--note=test'])
+        self.assert_no_fail(result)
+        self.assertTrue(result)