Repository: softlayer/softlayer-python
Pull request #2052 (2023-07-21 22:16:15)

--force option for slcli firewall add, firewall cancel command - issue #2032
Hi,

Fixes: #2032 

Please review this PR. 

Added force option for both slcli firewall add and cancel command.

Thanks,
Jayasilan


Patch:
diff --git a/SoftLayer/CLI/file/list.py b/SoftLayer/CLI/file/list.py
index 600fa6cd..540477b4 100644
--- a/SoftLayer/CLI/file/list.py
+++ b/SoftLayer/CLI/file/list.py
@@ -67,7 +67,11 @@
               default=','.join(DEFAULT_COLUMNS))
 @environment.pass_env
 def cli(env, sortby, columns, datacenter, username, storage_type, order):
-    """List file storage."""
+    """List file storage.
+
+    Example::
+            slcli file volume-list -d dal10 --storage-type endurance --sortby capacity_gb
+    """
     file_manager = SoftLayer.FileStorageManager(env.client)
     file_volumes = file_manager.list_file_volumes(datacenter=datacenter,
                                                   username=username,
diff --git a/SoftLayer/CLI/file/modify.py b/SoftLayer/CLI/file/modify.py
index 244868e4..27bb3f69 100644
--- a/SoftLayer/CLI/file/modify.py
+++ b/SoftLayer/CLI/file/modify.py
@@ -5,6 +5,7 @@
 import SoftLayer
 from SoftLayer.CLI import environment
 from SoftLayer.CLI import exceptions
+from SoftLayer.CLI import formatting
 
 
 CONTEXT_SETTINGS = {'token_normalize_func': lambda x: x.upper()}
@@ -31,9 +32,19 @@
                    'be 0.25. If original IOPS/GB for the volume is greater than 0.25, new IOPS/GB for the volume '
                    'must also be greater than 0.25.]',
               type=click.Choice(['0.25', '2', '4', '10']))
+@click.option('--force',  default=False, is_flag=True, help="Force modify")
 @environment.pass_env
-def cli(env, volume_id, new_size, new_iops, new_tier):
-    """Modify an existing file storage volume."""
+def cli(env, volume_id, new_size, new_iops, new_tier, force):
+    """Modify an existing file storage volume.
+
+    Example::
+            slcli file volume-modify 12345678 --new-size 1000 --new-iops 400
+    """
+    if not force:
+        if not (env.skip_confirmations or
+                formatting.confirm("This action will incur charges on your account. Continue?")):
+            raise exceptions.CLIAbort('Aborted')
+
     file_manager = SoftLayer.FileStorageManager(env.client)
 
     if new_tier is not None:
diff --git a/SoftLayer/CLI/file/options.py b/SoftLayer/CLI/file/options.py
index d66b526a..7ac60ab3 100644
--- a/SoftLayer/CLI/file/options.py
+++ b/SoftLayer/CLI/file/options.py
@@ -19,7 +19,12 @@
                    'add it to the --prices option using location short name, e.g. --prices dal13')
 @environment.pass_env
 def cli(env, prices, location=None):
-    """List all options for ordering a block storage"""
+    """List all options for ordering a block storage
+
+    Example::
+            slcli file volume-options
+            slcli file volume-options --prices dal13
+    """
 
     order_manager = SoftLayer.OrderingManager(env.client)
     items = order_manager.get_items(PACKAGE_STORAGE)
diff --git a/SoftLayer/CLI/firewall/add.py b/SoftLayer/CLI/firewall/add.py
index a612d289..9a9966d8 100644
--- a/SoftLayer/CLI/firewall/add.py
+++ b/SoftLayer/CLI/firewall/add.py
@@ -11,15 +11,11 @@
 
 @click.command(cls=SoftLayer.CLI.command.SLCommand, )
 @click.argument('target')
-@click.option('--firewall-type',
-              type=click.Choice(['vs', 'vlan', 'server']),
-              help='Firewall type',
-              required=True)
-@click.option('-ha', '--high-availability',
-              is_flag=True,
-              help='High available firewall option')
+@click.option('--firewall-type', type=click.Choice(['vs', 'vlan', 'server']), help='Firewall type', required=True)
+@click.option("-h", '--high-availability', is_flag=True, help='High available firewall option')
+@click.option('-f', '--force',  default=False, is_flag=True, help="Force addition of firewall to the server")
 @environment.pass_env
-def cli(env, target, firewall_type, high_availability):
+def cli(env, target, firewall_type, high_availability, force):
     """Create new firewall.
 
     TARGET: Id of the server the firewall will protect
@@ -43,8 +39,9 @@ def cli(env, target, firewall_type, high_availability):
         click.echo("Price: $%s monthly" % pkg[0]['prices'][0]['recurringFee'])
         click.echo("******************")
 
-        if not formatting.confirm("This action will incur charges on your account. Continue?"):
-            raise exceptions.CLIAbort('Aborted.')
+        if not force:
+            if not formatting.confirm("This action will incur charges on your account. Continue?"):
+                raise exceptions.CLIAbort('Aborted.')
 
     if firewall_type == 'vlan':
         mgr.add_vlan_firewall(target, ha_enabled=high_availability)
diff --git a/SoftLayer/CLI/firewall/cancel.py b/SoftLayer/CLI/firewall/cancel.py
index 1be9f3a0..2c6138fd 100644
--- a/SoftLayer/CLI/firewall/cancel.py
+++ b/SoftLayer/CLI/firewall/cancel.py
@@ -14,15 +14,16 @@
 @click.option('--firewall-type', required=True, show_default=True, default='vlan',
               type=click.Choice(['vlan', 'server'], case_sensitive=False),
               help='Firewall type.')
+@click.option('-f', '--force',  default=False, is_flag=True, help="Force cancel firewall of the server")
 @environment.pass_env
-def cli(env, identifier, firewall_type):
+def cli(env, identifier, firewall_type, force):
     """Cancels a firewall."""
 
     mgr = SoftLayer.FirewallManager(env.client)
-
-    if not (env.skip_confirmations or
-            formatting.confirm("This action will cancel a firewall from your account. Continue?")):
-        raise exceptions.CLIAbort('Aborted.')
+    if not force:
+        if not (env.skip_confirmations or
+                formatting.confirm("This action will cancel a firewall from your account. Continue?")):
+            raise exceptions.CLIAbort('Aborted.')
 
     if firewall_type == 'server':
         mgr.cancel_firewall(identifier, dedicated=False)


Test patch:
diff --git a/tests/CLI/modules/file_tests.py b/tests/CLI/modules/file_tests.py
index b8c7f00b..b9222574 100644
--- a/tests/CLI/modules/file_tests.py
+++ b/tests/CLI/modules/file_tests.py
@@ -820,3 +820,11 @@ def test_snapshot_get_notification_status(self, status):
     def test_volume_options(self):
         result = self.run_command(['file', 'volume-options'])
         self.assert_no_fail(result)
+
+    @mock.patch('SoftLayer.CLI.formatting.confirm')
+    def test_modify_order_no_force(self, confirm_mock):
+        confirm_mock.return_value = False
+        result = self.run_command(['file', 'volume-modify', '102'])
+
+        self.assertEqual(2, result.exit_code)
+        self.assertEqual('Aborted', result.exception.message)
diff --git a/tests/CLI/modules/firewall_tests.py b/tests/CLI/modules/firewall_tests.py
index 79d23969..0ccf2488 100644
--- a/tests/CLI/modules/firewall_tests.py
+++ b/tests/CLI/modules/firewall_tests.py
@@ -21,7 +21,7 @@ def test_list_firewalls(self):
     @mock.patch('SoftLayer.CLI.formatting.confirm')
     def test_add_vs(self, confirm_mock):
         confirm_mock.return_value = True
-        result = self.run_command(['firewall', 'add', '1000', '--firewall-type=vlan', '-ha'])
+        result = self.run_command(['firewall', 'add', '1000', '--firewall-type=vlan', '-h'])
         self.assert_no_fail(result)
         self.assertIn("Firewall is being created!", result.output)
 
@@ -158,3 +158,24 @@ def test_edit(self, confirm_mock):
     def test_monitoring(self):
         result = self.run_command(['firewall', 'monitoring', '123456'])
         print(result.output)
+
+    @mock.patch('SoftLayer.CLI.formatting.confirm')
+    def test_add_firewall_force(self, confirm_mock):
+        confirm_mock.return_value = False
+        result = self.run_command(['firewall', 'add', '1000', '--firewall-type=vlan', '-h', '--force'])
+        self.assert_no_fail(result)
+        self.assertIn("Firewall is being created!", result.output)
+
+    @mock.patch('SoftLayer.CLI.formatting.confirm')
+    def test_add_firewall_no_force(self, confirm_mock):
+        confirm_mock.return_value = False
+        result = self.run_command(['firewall', 'add', '1000', '--firewall-type=vlan', '-h'])
+        self.assertEqual(2, result.exit_code)
+
+    @mock.patch('SoftLayer.CLI.formatting.confirm')
+    def test_cancel_firewall_no_force(self, confirm_mock):
+        confirm_mock.return_value = False
+        result = self.run_command(['firewall', 'cancel', 'vlan:1234'])
+        self.assertEqual(2, result.exit_code)
+        print(result.output)
+        self.assertEqual('Aborted.', result.exception.message)