diff options
| author | Artem Goncharov <Artem.goncharov@gmail.com> | 2020-06-09 11:35:46 +0200 |
|---|---|---|
| committer | Artem Goncharov <artem.goncharov@gmail.com> | 2021-02-02 08:14:34 +0000 |
| commit | 119d2fae2567285b9149b2c737d7d4452b59288c (patch) | |
| tree | 8e9bef2e7bb22131a052cbf70a7365bda49ad88a /openstackclient/common | |
| parent | 01a53fa96fe2fbd67682850ee7ce9ab140c9211b (diff) | |
| download | python-openstackclient-119d2fae2567285b9149b2c737d7d4452b59288c.tar.gz | |
project cleanup
New implementation of the project cleanup based on the sdk.project_cleanup.
It is implemented as an additional OSC operation and will ideally obsolete the
`openstack project purge` giving flexibility to extend services support,
parallelization, filters, etc.
Change-Id: Ie08877f182379f73e5ec5ad4daaf84b3092c829c
Diffstat (limited to 'openstackclient/common')
| -rw-r--r-- | openstackclient/common/project_cleanup.py | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/openstackclient/common/project_cleanup.py b/openstackclient/common/project_cleanup.py new file mode 100644 index 00000000..f2536354 --- /dev/null +++ b/openstackclient/common/project_cleanup.py @@ -0,0 +1,140 @@ +# Copyright 2020 OpenStack Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +import getpass +import logging +import os +import queue + +from cliff.formatters import table +from osc_lib.command import command + +from openstackclient.i18n import _ +from openstackclient.identity import common as identity_common + + +LOG = logging.getLogger(__name__) + + +def ask_user_yesno(msg, default=True): + """Ask user Y/N question + + :param str msg: question text + :param bool default: default value + :return bool: User choice + """ + while True: + answer = getpass._raw_input( + '{} [{}]: '.format(msg, 'y/N' if not default else 'Y/n')) + if answer in ('y', 'Y', 'yes'): + return True + elif answer in ('n', 'N', 'no'): + return False + + +class ProjectCleanup(command.Command): + _description = _("Clean resources associated with a project") + + def get_parser(self, prog_name): + parser = super(ProjectCleanup, self).get_parser(prog_name) + parser.add_argument( + '--dry-run', + action='store_true', + help=_("List a project's resources") + ) + project_group = parser.add_mutually_exclusive_group(required=True) + project_group.add_argument( + '--auth-project', + action='store_true', + help=_('Delete resources of the project used to authenticate') + ) + project_group.add_argument( + '--project', + metavar='<project>', + help=_('Project to clean (name or ID)') + ) + parser.add_argument( + '--created-before', + metavar='<YYYY-MM-DDTHH24:MI:SS>', + help=_('Drop resources created before the given time') + ) + parser.add_argument( + '--updated-before', + metavar='<YYYY-MM-DDTHH24:MI:SS>', + help=_('Drop resources updated before the given time') + ) + identity_common.add_project_domain_option_to_parser(parser) + return parser + + def take_action(self, parsed_args): + sdk = self.app.client_manager.sdk_connection + + if parsed_args.auth_project: + project_connect = sdk + elif parsed_args.project: + project = sdk.identity.find_project( + name_or_id=parsed_args.project, + ignore_missing=False) + project_connect = sdk.connect_as_project(project) + + if project_connect: + status_queue = queue.Queue() + parsed_args.max_width = int(os.environ.get('CLIFF_MAX_TERM_WIDTH', + 0)) + parsed_args.fit_width = bool(int(os.environ.get('CLIFF_FIT_WIDTH', + 0))) + parsed_args.print_empty = False + table_fmt = table.TableFormatter() + + self.log.info('Searching resources...') + + filters = {} + if parsed_args.created_before: + filters['created_at'] = parsed_args.created_before + + if parsed_args.updated_before: + filters['updated_at'] = parsed_args.updated_before + + project_connect.project_cleanup(dry_run=True, + status_queue=status_queue, + filters=filters) + + data = [] + while not status_queue.empty(): + resource = status_queue.get_nowait() + data.append( + (type(resource).__name__, resource.id, resource.name)) + status_queue.task_done() + status_queue.join() + table_fmt.emit_list( + ('Type', 'ID', 'Name'), + data, + self.app.stdout, + parsed_args + ) + + if parsed_args.dry_run: + return + + confirm = ask_user_yesno( + _("These resources will be deleted. Are you sure"), + default=False) + + if confirm: + self.log.warning(_('Deleting resources')) + + project_connect.project_cleanup(dry_run=False, + status_queue=status_queue, + filters=filters) |
