From fcae03ec81f855ff17b950a9c48c4946ad8be32e Mon Sep 17 00:00:00 2001 From: Hugo Brito Date: Thu, 12 Sep 2024 19:11:23 -0300 Subject: [PATCH] Add --remove parameter to patch-strategy This commit introduces a new `--remove` parameter to the `patch-strategy` CLI, enabling users to remove a patch by specifying the `patch_id`. Test Plan: PASS: Verify `dcmanager patch-strategy create` work with and without --remove. Failure Path: PASS: Verify CLI error when --remove is used with --upload-only. Story: 2010676 Task: 51058 Depends-On: https://review.opendev.org/c/starlingx/distcloud/+/929566 Change-Id: Iaa2d68339a4c76665ec1f5aff9e9673f32bc64ae Signed-off-by: Hugo Brito --- .../api/v1/sw_patch_manager.py | 2 +- .../commands/v1/sw_patch_manager.py | 20 ++++++++-- .../tests/v1/test_patch_update_strategy.py | 39 +++++++++++++++++++ 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/distributedcloud-client/dcmanagerclient/api/v1/sw_patch_manager.py b/distributedcloud-client/dcmanagerclient/api/v1/sw_patch_manager.py index ab25e624..f89780f0 100644 --- a/distributedcloud-client/dcmanagerclient/api/v1/sw_patch_manager.py +++ b/distributedcloud-client/dcmanagerclient/api/v1/sw_patch_manager.py @@ -22,4 +22,4 @@ SW_UPDATE_TYPE_PATCH = "patch" class SwPatchManager(SwUpdateManager): def __init__(self, http_client): super().__init__(http_client, update_type=SW_UPDATE_TYPE_PATCH) - self.extra_args = ["upload-only", "patch_id"] + self.extra_args = ["upload-only", "patch_id", "remove"] diff --git a/distributedcloud-client/dcmanagerclient/commands/v1/sw_patch_manager.py b/distributedcloud-client/dcmanagerclient/commands/v1/sw_patch_manager.py index ebed1e7a..ed24f88e 100644 --- a/distributedcloud-client/dcmanagerclient/commands/v1/sw_patch_manager.py +++ b/distributedcloud-client/dcmanagerclient/commands/v1/sw_patch_manager.py @@ -15,6 +15,7 @@ # from dcmanagerclient.commands.v1 import sw_update_manager +from dcmanagerclient import exceptions class SwPatchManagerMixin: @@ -59,6 +60,13 @@ class CreatePatchUpdateStrategy( help="Stops strategy after uploading patches to subclouds", ) + parser.add_argument( + "--remove", + required=False, + action="store_true", + help="Remove the patch on the subcloud.", + ) + parser.add_argument( "patch_id", help="The patch ID to upload/apply on the subcloud.", @@ -68,10 +76,14 @@ class CreatePatchUpdateStrategy( def process_custom_params(self, parsed_args, kwargs_dict): """Updates kwargs dictionary from parsed_args for patching""" - if parsed_args.upload_only: - kwargs_dict["upload-only"] = "true" - else: - kwargs_dict["upload-only"] = "false" + + # Raise exception if both --upload-only and --remove are specified + if parsed_args.upload_only and parsed_args.remove: + msg = "Cannot specify both --upload-only and --remove" + raise exceptions.DCManagerClientException(msg) + + kwargs_dict["upload-only"] = str(parsed_args.upload_only).lower() + kwargs_dict["remove"] = str(parsed_args.remove).lower() kwargs_dict["patch_id"] = parsed_args.patch_id diff --git a/distributedcloud-client/dcmanagerclient/tests/v1/test_patch_update_strategy.py b/distributedcloud-client/dcmanagerclient/tests/v1/test_patch_update_strategy.py index a93c2f7c..51fae564 100644 --- a/distributedcloud-client/dcmanagerclient/tests/v1/test_patch_update_strategy.py +++ b/distributedcloud-client/dcmanagerclient/tests/v1/test_patch_update_strategy.py @@ -6,6 +6,7 @@ from dcmanagerclient.commands.v1 import sw_patch_manager as cli_cmd +from dcmanagerclient.exceptions import DCManagerClientException from dcmanagerclient.tests import base from dcmanagerclient.tests.v1 import utils from dcmanagerclient.tests.v1.mixins import UpdateStrategyMixin @@ -81,3 +82,41 @@ class TestPatchUpdateStrategy(UpdateStrategyMixin, base.BaseCommandTest): self.assertEqual(results[0], self.expected_strategy_type) self.assertEqual(fields[-4], "upload only") self.assertEqual(results[-4], True) + + def test_create_strategy_remove(self): + """Test that a strategy can be created with the --remove option""" + + # mock the result of the API call + strategy = utils.make_strategy( + strategy_type=self.expected_strategy_type, + extra_args={"remove": True, "patch_id": "stx-10.1"}, + ) + + # mock that there is no pre-existing strategy + self.manager_to_test.create_sw_update_strategy.return_value = strategy + + # invoke the backend method for the CLI. + # Returns a tuple of field descriptions, and a second tuple of values + _, results = self.call(self.create_command, ["stx-10.1", "--remove"]) + + self.assertEqual(len(results), self.results_length) + self.assertEqual(results[0], self.expected_strategy_type) + + def test_create_strategy_upload_only_and_remove(self): + """Test that a strategy can be created with the --remove option""" + + # mock the result of the API call + strategy = utils.make_strategy( + strategy_type=self.expected_strategy_type, + extra_args={"upload-only": True, "remove": True, "patch_id": "stx-10.1"}, + ) + + # mock that there is no pre-existing strategy + self.manager_to_test.create_sw_update_strategy.return_value = strategy + + self.assertRaises( + DCManagerClientException, + self.call, + self.create_command, + ["stx-10.1", "--upload-only", "--remove"], + )