Repository: softlayer/softlayer-python
Pull request #1285 (2020-06-18 21:23:31)

Implement slcli vlan edit functionality.
Implement slcli vlan edit functionalityhttps://github.com/softlayer/softlayer-python/issues/1282.

**slcli vlan edit --help**

Usage: slcli vlan edit [OPTIONS] IDENTIFIER

  Edit a vlan's details.

Options:
  -n, --name TEXT  The optional name for this VLAN
  -e, --note TEXT  The note for this vlan.
  -g, --tag TEXT   Tags to set e.g. "tag1,tag2", or empty string to remove all
  -h, --help       Show this message and exit.

The SoftLayer_Network_Vlan::editObject request allow to edit the note attribute but this is not shown by ui and api too.


Patch:
diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py
index cc67a7d2..60484114 100644
--- a/SoftLayer/CLI/routes.py
+++ b/SoftLayer/CLI/routes.py
@@ -322,6 +322,7 @@
 
     ('vlan', 'SoftLayer.CLI.vlan'),
     ('vlan:detail', 'SoftLayer.CLI.vlan.detail:cli'),
+    ('vlan:edit', 'SoftLayer.CLI.vlan.edit:cli'),
     ('vlan:list', 'SoftLayer.CLI.vlan.list:cli'),
 
     ('summary', 'SoftLayer.CLI.summary:cli'),
diff --git a/SoftLayer/CLI/vlan/edit.py b/SoftLayer/CLI/vlan/edit.py
new file mode 100644
index 00000000..c623e5d2
--- /dev/null
+++ b/SoftLayer/CLI/vlan/edit.py
@@ -0,0 +1,37 @@
+"""Edit a vlan's details."""
+# :license: MIT, see LICENSE for more details.
+
+import click
+
+import SoftLayer
+from SoftLayer.CLI import environment
+from SoftLayer.CLI import helpers
+
+
+@click.command()
+@click.argument('identifier')
+@click.option('--name', '-n',
+              help="The optional name for this VLAN")
+@click.option('--note', '-e',
+              help="The note for this vlan.")
+@click.option('--tags', '-g',
+              multiple=True,
+              help='Tags to set e.g. "tag1,tag2", or empty string to remove all'
+              )
+@environment.pass_env
+def cli(env, identifier, name, note, tags):
+    """Edit a vlan's details."""
+
+    new_tags = None
+
+    if tags:
+        new_tags = ','.join(tags)
+
+    mgr = SoftLayer.NetworkManager(env.client)
+    vlan_id = helpers.resolve_id(mgr.resolve_vlan_ids, identifier, 'VLAN')
+    vlan = mgr.edit(vlan_id, name=name, note=note, tags=new_tags)
+
+    if vlan:
+        click.secho("Vlan edited successfully", fg='green')
+    else:
+        click.secho("Failed to edit the vlan", fg='red')
diff --git a/SoftLayer/fixtures/SoftLayer_Network_Vlan.py b/SoftLayer/fixtures/SoftLayer_Network_Vlan.py
index 5c7d7232..b1863253 100644
--- a/SoftLayer/fixtures/SoftLayer_Network_Vlan.py
+++ b/SoftLayer/fixtures/SoftLayer_Network_Vlan.py
@@ -7,3 +7,6 @@
     'vlanNumber': 4444,
     'firewallInterfaces': None
 }
+
+editObject = True
+setTags = True
diff --git a/SoftLayer/managers/network.py b/SoftLayer/managers/network.py
index dbfb9c3f..b3f6f7b6 100644
--- a/SoftLayer/managers/network.py
+++ b/SoftLayer/managers/network.py
@@ -7,12 +7,19 @@
 """
 import collections
 import json
+import logging
+
+from SoftLayer.decoration import retry
 
 from SoftLayer import exceptions
 from SoftLayer import utils
 
 from SoftLayer.managers import event_log
 
+LOGGER = logging.getLogger(__name__)
+
+# pylint: disable=too-many-public-methods
+
 DEFAULT_SUBNET_MASK = ','.join(['hardware',
                                 'datacenter',
                                 'ipAddressCount',
@@ -685,3 +692,38 @@ def get_nas_credentials(self, identifier, **kwargs):
         """
         result = self.network_storage.getObject(id=identifier, **kwargs)
         return result
+
+    def edit(self, instance_id, name=None, note=None, tags=None):
+        """Edit a vlan.
+
+        :param integer instance_id: the instance ID to edit.
+        :param string name: valid name.
+        :param string note: note about this particular vlan.
+        :param string tags: tags to set on the vlan as a comma separated list.
+                            Use the empty string to remove all tags.
+        :returns: bool -- True or an Exception
+        """
+
+        obj = {}
+
+        if tags is not None:
+            self.set_tags(tags, vlan_id=instance_id)
+
+        if name:
+            obj['name'] = name
+
+        if note:
+            obj['note'] = note
+
+        if not obj:
+            return True
+
+        return self.vlan.editObject(obj, id=instance_id)
+
+    @retry(logger=LOGGER)
+    def set_tags(self, tags, vlan_id):
+        """Sets tags on a vlan with a retry decorator
+
+        Just calls vlan.setTags, but if it fails from an APIError will retry.
+        """
+        self.vlan.setTags(tags, id=vlan_id)
diff --git a/docs/cli/vlan.rst b/docs/cli/vlan.rst
index 1733f40e..6fc084da 100644
--- a/docs/cli/vlan.rst
+++ b/docs/cli/vlan.rst
@@ -7,6 +7,10 @@ VLANs
     :prog: vlan detail
     :show-nested:
 
+.. click:: SoftLayer.CLI.vlan.edit:cli
+    :prog: vlan edit
+    :show-nested:
+
 .. click:: SoftLayer.CLI.vlan.list:cli
     :prog: vlan list
     :show-nested:


Test patch:
diff --git a/tests/CLI/modules/vlan_tests.py b/tests/CLI/modules/vlan_tests.py
index 86b15507..1cdd3f3f 100644
--- a/tests/CLI/modules/vlan_tests.py
+++ b/tests/CLI/modules/vlan_tests.py
@@ -4,6 +4,8 @@
 
     :license: MIT, see LICENSE for more details.
 """
+import mock
+
 from SoftLayer import testing
 
 
@@ -76,3 +78,19 @@ def test_detail_hardware_without_hostname(self):
         vlan_mock.return_value = getObject
         result = self.run_command(['vlan', 'detail', '1234'])
         self.assert_no_fail(result)
+
+    @mock.patch('SoftLayer.CLI.vlan.edit.click')
+    def test_vlan_edit(self, click):
+        result = self.run_command(['vlan', 'edit', '--name=nameTest', '--note=noteTest', '--tags=tag1,tag2', '100'])
+        click.secho.assert_called_with('Vlan edited successfully', fg='green')
+        self.assert_no_fail(result)
+        self.assert_called_with('SoftLayer_Network_Vlan', 'editObject', identifier=100)
+
+    @mock.patch('SoftLayer.CLI.vlan.edit.click')
+    def test_vlan_edit_failure(self, click):
+        mock = self.set_mock('SoftLayer_Network_Vlan', 'editObject')
+        mock.return_value = False
+        result = self.run_command(['vlan', 'edit', '--name=nameTest', '--note=noteTest', '--tags=tag1,tag2', '100'])
+        click.secho.assert_called_with('Failed to edit the vlan', fg='red')
+        self.assert_no_fail(result)
+        self.assert_called_with('SoftLayer_Network_Vlan', 'editObject', identifier=100)
diff --git a/tests/managers/network_tests.py b/tests/managers/network_tests.py
index fd986e2e..165d04b7 100644
--- a/tests/managers/network_tests.py
+++ b/tests/managers/network_tests.py
@@ -625,3 +625,12 @@ def test_get_cci_event_logs(self):
         _filter = {'objectName': {'operation': 'CCI'}}
         self.assert_called_with('SoftLayer_Event_Log', 'getAllObjects', filter=_filter)
         self.assertEqual(100, log['accountId'])
+
+    def test_vlan_edit(self):
+        vlan_id = 100
+        name = "test"
+        note = "test note"
+        tags = "tag1,tag2"
+
+        self.network.edit(vlan_id, name, note, tags)
+        self.assert_called_with('SoftLayer_Network_Vlan', 'editObject')