diff --git a/etc-conf/subscription-manager.completion.sh b/etc-conf/subscription-manager.completion.sh index f5594437d7..e6cc6a5807 100644 --- a/etc-conf/subscription-manager.completion.sh +++ b/etc-conf/subscription-manager.completion.sh @@ -87,26 +87,6 @@ _subscription_manager_unregister() COMPREPLY=($(compgen -W "${opts}" -- ${1})) } -_subscription_manager_remove() -{ - # try to autocomplete serial number as well - case $prev in - --serial) - SERIALS=$(LANG=C /usr/sbin/subscription-manager list --consumed 2>/dev/null | sed -ne "s|Serial:\s*\(\S*\)|\1|p" ) - COMPREPLY=($(compgen -W "${SERIALS}" -- ${1})) - return 0 - ;; - --pool) - POOLS=$(LANG=C /usr/sbin/subscription-manager list --consumed 2>/dev/null | sed -ne "s|Pool ID:\s*(\S*\)|\1|p" ) - COMPREPLY=($(compgen -W "${POOLS}" -- ${1})) - return 0 - ;; - esac - local opts="--serial --pool --all - ${_subscription_manager_common_opts}" - COMPREPLY=($(compgen -W "${opts}" -- ${1})) -} - _subscription_manager_clean() { local opts="-h --help" @@ -261,7 +241,7 @@ _subscription_manager() # top-level commands and options opts="attach auto-attach clean config environments facts identity list orgs - repo-override plugins redeem refresh register release remove repos status + repo-override plugins redeem refresh register release repos status syspurpose unregister version ${_subscription_manager_help_opts}" case "${first}" in @@ -289,10 +269,6 @@ _subscription_manager() "_subscription_manager_attach" "${cur}" "${prev}" return 0 ;; - remove) - "_subscription_manager_remove" "${cur}" "${prev}" - return 0 - ;; auto-attach) "_subscription_manager_auto_attach" "${cur}" "${prev}" return 0 diff --git a/man/subscription-manager.8 b/man/subscription-manager.8 index 25d1ebf884..2b77d11175 100644 --- a/man/subscription-manager.8 +++ b/man/subscription-manager.8 @@ -29,7 +29,7 @@ Subscription Manager performs several key operations: .IP * It lists both available and used subscriptions. .IP -* It allows administrators to both attach specific subscriptions to a system and remove those subscriptions. +* It allows administrators to attach specific subscriptions to a system. .PP Subscription Manager can be used to auto-attach subscriptions to a system, as well. The .B subscription-manager @@ -83,59 +83,56 @@ must be passed as system arguments in a non-interactive session. 4. auto-attach .IP -5. remove +5. release .IP -6. release +6. redeem .IP -8. redeem +7. list .IP -9. list +8. refresh .IP -10. refresh +9. environments .IP -11. environments +10. repos .IP -12. repos +11. orgs .IP -13. orgs +12. plugins .IP -14. plugins +13. identity .IP -15. identity +14. facts .IP -16. facts +15. clean .IP -17. clean +16. config .IP -18. config +17. version .IP -19. version +18. status .IP -20. status +19. syspurpose .IP -21. syspurpose - -.IP -22. repo-override +20. repo-override .RE -Following commands were deprecated: subscribe and unsubscribe +Following commands were deprecated: subscribe. .SS COMMON OPTIONS .TP @@ -351,33 +348,6 @@ Disables the auto-attach option for the system. If auto-attach is disabled, then .B --show Shows whether auto-attach is enabled on the systems. -.SS REMOVE OPTIONS -The -.B remove -command removes a subscription from the system. (This does not uninstall the associated products.) - -.TP -.B --serial=SERIALNUMBER -Gives the serial number of the subscription certificate for the specific product to remove from the system. Subscription certificates attached to a system are in a certificate, in -.B /etc/pki/entitlement/.pem. -To remove multiple subscriptions, use the -.B --serial -option multiple times. - -.TP -.B --pool=POOLID -Removes all subscription certificates for the specified pool id from the system. -To remove multiple sets of subscriptions, use the -.B --pool -option multiple times. - -.TP -.B --all -Removes -.I all -of the subscriptions attached to a system. - - .SS RELEASE OPTIONS The .B release @@ -1013,16 +983,12 @@ Overall Status: Insufficient .RE .SS DEPRECATED COMMANDS -As the structures of subscription configuration have changed, some of the original management commands have become obsolete. These commands have been replaced with updated commands. +As the structures of subscription configuration have changed, some of the original management commands have become obsolete. Some of these commands have been replaced with updated commands. .TP .B subscribe This has been replaced with attach. A similar registration option, \fB--subscribe\fP, has also be replaced with \fB--auto-attach\fP. -.TP -.B unsubscribe -This has been replaced with \fBremove\fP. - .SH USAGE .B subscription-manager has two major tasks: diff --git a/src/subscription_manager/cli_command/remove.py b/src/subscription_manager/cli_command/remove.py deleted file mode 100644 index 3e58b1dd48..0000000000 --- a/src/subscription_manager/cli_command/remove.py +++ /dev/null @@ -1,212 +0,0 @@ -# -# Subscription manager command line utility. -# -# Copyright (c) 2021 Red Hat, Inc. -# -# This software is licensed to you under the GNU General Public License, -# version 2 (GPLv2). There is NO WARRANTY for this software, express or -# implied, including the implied warranties of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 -# along with this software; if not, see -# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -# -# Red Hat trademarks are not licensed under GPLv2. No permission is -# granted to use or replicate Red Hat trademarks that are incorporated -# in this software or its documentation. -# -import logging -import os - -import rhsm.connection as connection - -from rhsmlib.services import entitlement - -from subscription_manager.cli import system_exit -from subscription_manager.cli_command.cli import CliCommand, handle_exception -from subscription_manager.i18n import ungettext, ugettext as _ -from subscription_manager.utils import unique_list_items - -log = logging.getLogger(__name__) - - -class RemoveCommand(CliCommand): - def __init__(self): - super(RemoveCommand, self).__init__(self._command_name(), self._short_description(), self._primary()) - - self.parser.add_argument( - "--serial", - action="append", - dest="serials", - metavar="SERIAL", - help=_("certificate serial number to remove (can be specified more than once)"), - ) - self.parser.add_argument( - "--pool", - action="append", - dest="pool_ids", - metavar="POOL_ID", - help=_("the ID of the pool to remove (can be specified more than once)"), - ) - self.parser.add_argument( - "--all", - dest="all", - action="store_true", - help=_("remove all subscriptions from this system"), - ) - - def _short_description(self): - return _("Remove all or specific subscriptions from this system") - - def _command_name(self): - return "remove" - - def _primary(self): - return True - - def _validate_options(self): - if self.options.serials: - bad = False - for serial in self.options.serials: - if not serial.isdigit(): - print(_("Error: '{serial}' is not a valid serial number").format(serial=serial)) - bad = True - if bad: - system_exit(os.EX_USAGE) - elif self.options.pool_ids: - if not self.cp.has_capability("remove_by_pool_id"): - system_exit( - os.EX_UNAVAILABLE, - _( - "Error: The registered entitlement server does not support remove --pool." - "\nInstead, use the remove --serial option." - ), - ) - elif not self.options.all and not self.options.pool_ids: - system_exit( - os.EX_USAGE, - _("Error: This command requires that you specify one of --serial, --pool or --all."), - ) - - def _print_unbind_ids_result(self, success, failure, id_name): - if success: - if id_name == "pools": - print(_("The entitlement server successfully removed these pools:")) - elif id_name == "serial numbers": - print(_("The entitlement server successfully removed these serial numbers:")) - else: - print(_("The entitlement server successfully removed these IDs:")) - for id_ in success: - print(" {id_}".format(id_=id_)) - if failure: - if id_name == "pools": - print(_("The entitlement server failed to remove these pools:")) - elif id_name == "serial numbers": - print(_("The entitlement server failed to remove these serial numbers:")) - else: - print(_("The entitlement server failed to remove these IDs:")) - for id_ in failure: - print(" {id_}".format(id_=id_)) - - def _do_command(self): - """ - Executes the command. - """ - self._validate_options() - return_code = 0 - if self.is_registered(): - ent_service = entitlement.EntitlementService(self.cp) - try: - if self.options.all: - total = ent_service.remove_all_entitlements() - # total will be None on older Candlepins that don't - # support returning the number of subscriptions unsubscribed from - if total is None: - print(_("All subscriptions have been removed at the server.")) - else: - count = total["deletedRecords"] - print( - ungettext( - "%s subscription removed at the server.", - "%s subscriptions removed at the server.", - count, - ) - % count - ) - else: - # Try to remove subscriptions defined by pool IDs first (remove --pool=...) - if self.options.pool_ids: - ( - removed_pools, - unremoved_pools, - removed_serials, - ) = ent_service.remove_entitlements_by_pool_ids(self.options.pool_ids) - if not removed_pools: - return_code = 1 - self._print_unbind_ids_result(removed_pools, unremoved_pools, "pools") - else: - removed_serials = [] - # Then try to remove subscriptions defined by serials (remove --serial=...) - unremoved_serials = [] - if self.options.serials: - serials = unique_list_items(self.options.serials) - # Don't remove serials already removed by a pool - serials_to_remove = [serial for serial in serials if serial not in removed_serials] - _removed_serials, unremoved_serials = ent_service.remove_entitlements_by_serials( - serials_to_remove - ) - removed_serials.extend(_removed_serials) - if not _removed_serials: - return_code = 1 - # Print final result of removing pools - self._print_unbind_ids_result(removed_serials, unremoved_serials, "serial numbers") - except connection.GoneException as ge: - raise ge - except connection.RestlibException as err: - log.error(err) - - system_exit(os.EX_SOFTWARE, err) - except Exception as e: - handle_exception( - _("Unable to perform remove due to the following exception: {e}").format(e=e), e - ) - else: - # We never got registered, just remove the cert - try: - if self.options.all: - total = 0 - for ent in self.entitlement_dir.list(): - ent.delete() - total = total + 1 - print( - ungettext( - "{total} subscription removed from this system.", - "{total} subscriptions removed from this system.", - total, - ).format(total=total) - ) - else: - if self.options.serials or self.options.pool_ids: - serials = self.options.serials or [] - pool_ids = self.options.pool_ids or [] - count = 0 - for ent in self.entitlement_dir.list(): - ent_pool_id = str(getattr(ent.pool, "id", None) or "") - if str(ent.serial) in serials or ent_pool_id in pool_ids: - ent.delete() - print( - _( - "Subscription with serial number {serial} removed from this system" - ).format(serial=str(ent.serial)) - ) - count = count + 1 - if count == 0: - return_code = 1 - except Exception as e: - handle_exception( - _("Unable to perform remove due to the following exception: {e}").format(e=e), e - ) - - # it is okay to call this no matter what happens above, - # it's just a notification to perform a check - self._request_validity_check() - return return_code diff --git a/src/subscription_manager/managercli.py b/src/subscription_manager/managercli.py index ab8a36c12a..e9a1b8aa4f 100644 --- a/src/subscription_manager/managercli.py +++ b/src/subscription_manager/managercli.py @@ -38,7 +38,6 @@ from subscription_manager.cli_command.refresh import RefreshCommand from subscription_manager.cli_command.register import RegisterCommand from subscription_manager.cli_command.release import ReleaseCommand -from subscription_manager.cli_command.remove import RemoveCommand from subscription_manager.cli_command.repos import ReposCommand from subscription_manager.cli_command.status import StatusCommand from subscription_manager.cli_command.syspurpose import SyspurposeCommand @@ -67,7 +66,6 @@ def __init__(self): StatusCommand, EnvironmentsCommand, VersionCommand, - RemoveCommand, AttachCommand, PluginsCommand, AutohealCommand, diff --git a/test/cli_command/test_remove.py b/test/cli_command/test_remove.py deleted file mode 100644 index d39a5cd21b..0000000000 --- a/test/cli_command/test_remove.py +++ /dev/null @@ -1,37 +0,0 @@ -import os - -from ..test_managercli import TestCliProxyCommand -from subscription_manager import managercli - - -class TestRemoveCommand(TestCliProxyCommand): - command_class = managercli.RemoveCommand - - def test_validate_serial(self): - self.cc.main(["--serial", "12345"]) - self.cc._validate_options() - - def test_validate_serial_not_numbers(self): - self.cc.main(["--serial", "this is not a number"]) - try: - self.cc._validate_options() - except SystemExit as e: - self.assertEqual(e.code, os.EX_USAGE) - - def test_serial_no_value(self): - try: - self.cc.main(["--serial"]) - except SystemExit as e: - self.assertEqual(e.code, 2) - - def test_validate_access_to_remove_by_pool(self): - self.cc.main(["--pool", "a2ee88488bbd32ed8edfa2"]) - self.cc.cp._capabilities = ["remove_by_pool_id"] - self.cc._validate_options() - - def test_validate_no_access_to_remove_by_pool(self): - self.cc.main(["--pool", "a2ee88488bbd32ed8edfa2"]) - try: - self.cc._validate_options() - except SystemExit as e: - self.assertEqual(e.code, 69) diff --git a/test/test_remove.py b/test/test_remove.py deleted file mode 100644 index 38224e2f17..0000000000 --- a/test/test_remove.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright (c) 2012 Red Hat, Inc. -# -# This software is licensed to you under the GNU General Public License, -# version 2 (GPLv2). There is NO WARRANTY for this software, express or -# implied, including the implied warranties of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 -# along with this software; if not, see -# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -# -# Red Hat trademarks are not licensed under GPLv2. No permission is -# granted to use or replicate Red Hat trademarks that are incorporated -# in this software or its documentation. -# - -from subscription_manager import managercli -from subscription_manager import injection as inj - -from .stubs import ( - StubEntitlementDirectory, - StubProductDirectory, - StubEntActionInvoker, - StubEntitlementCertificate, - StubProduct, - StubPool, -) -from . import fixture - - -# This is a copy of CliUnSubscribeTests for the new name. -class CliRemoveTests(fixture.SubManFixture): - def test_unsubscribe_registered(self): - cmd = managercli.RemoveCommand() - - mock_identity = self._inject_mock_valid_consumer() - managercli.EntCertActionInvoker = StubEntActionInvoker - - cmd.main(["--all"]) - self.assertEqual(cmd.cp.called_unbind_uuid, mock_identity.uuid) - - serial1 = "123456" - cmd.main(["--serial=%s" % serial1]) - self.assertEqual(cmd.cp.called_unbind_serial, [serial1]) - cmd.cp.reset() - - serial2 = "789012" - cmd.main(["--serial=%s" % serial1, "--serial=%s" % serial2]) - self.assertEqual(cmd.cp.called_unbind_serial, [serial1, serial2]) - cmd.cp.reset() - - pool_id1 = "39993922b" - cmd.main( - ["--serial=%s" % serial1, "--serial=%s" % serial2, "--pool=%s" % pool_id1, "--pool=%s" % pool_id1] - ) - self.assertEqual(cmd.cp.called_unbind_serial, [serial1, serial2]) - self.assertEqual(cmd.cp.called_unbind_pool_id, [pool_id1]) - - def test_unsubscribe_unregistered(self): - prod = StubProduct("stub_product") - ent = StubEntitlementCertificate(prod) - - inj.provide(inj.ENT_DIR, StubEntitlementDirectory([ent])) - inj.provide(inj.PROD_DIR, StubProductDirectory([])) - cmd = managercli.RemoveCommand() - - self._inject_mock_invalid_consumer() - - cmd.main(["--all"]) - self.assertTrue(cmd.entitlement_dir.list_called) - self.assertTrue(ent.is_deleted) - - prod = StubProduct("stub_product") - pool = StubPool("stub_pool") - ent1 = StubEntitlementCertificate(prod) - ent2 = StubEntitlementCertificate(prod) - ent3 = StubEntitlementCertificate(prod) - ent4 = StubEntitlementCertificate(prod, pool=pool) - - inj.provide(inj.ENT_DIR, StubEntitlementDirectory([ent1, ent2, ent3, ent4])) - inj.provide(inj.PROD_DIR, StubProductDirectory([])) - cmd = managercli.RemoveCommand() - - cmd.main(["--serial=%s" % ent1.serial, "--serial=%s" % ent3.serial, "--pool=%s" % ent4.pool.id]) - self.assertTrue(cmd.entitlement_dir.list_called) - self.assertTrue(ent1.is_deleted) - self.assertFalse(ent2.is_deleted) - self.assertTrue(ent3.is_deleted) - self.assertTrue(ent4.is_deleted)