Adds tuskar-delete-roles command

The current Tuskar API doesn't cover the role resource lifecycle.
For development purposes there is no easy way to delete existing
roles that were created with tuskar-load-role and friends.

This review adds a tuskar-delete-roles utility that takes a --uuids
list of ids to delete. If any of the specified role uuids do not
exist, an unknownUUID exception is raised. If any of the specified
uuids are in use by an existing plan, a OvercloudRoleInUse exception
is raised. In case of either of the above, no roles are deleted and
the operation exits.

The --dryrun flag can be specified which still goes through the
validation above but still does not perform any deletions when
that passes.

Example invocation:

tuskar-delete-roles --config-file ~/tuskar.conf --dryrun --uuids
    c3b43c3c-e69b-4db7-b0df-3bf2bb8c04cf
    5cffe8b6-df60-4cc6-92c6-c8067f0067eb

Change-Id: Idb397fd0d6d35b143646d42b171deebc1bce6b36
This commit is contained in:
marios 2015-03-18 15:32:26 +02:00
parent 9fe1c3a893
commit bcb854540e
4 changed files with 156 additions and 0 deletions

View File

@ -27,6 +27,7 @@ console_scripts =
tuskar-dbsync = tuskar.cmd.dbsync:main
tuskar-load-roles = tuskar.cmd.load_roles:main
tuskar-load-seed = tuskar.cmd.load_seed:main
tuskar-delete-roles = tuskar.cmd.delete_roles:main
[build_sphinx]
all_files = 1

View File

@ -0,0 +1,47 @@
#!/usr/bin/env python
#
# Copyright 2015 Red Hat
#
# 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.
from __future__ import print_function
import sys
from oslo.config import cfg
from tuskar.common import service
from tuskar.storage.delete_roles import delete_roles
def _print_names(message, names):
print("{0}: \n {1}".format(message, '\n '.join(names)))
cfg.CONF.register_cli_opt(cfg.BoolOpt('dryrun', short='n', default=False))
cfg.CONF.register_cli_opt(cfg.ListOpt(
'uuids', help='List of role uuid to delete'))
def main(argv=None):
if argv is None:
argv = sys.argv
index = argv.index('--uuids')
service.prepare_service(argv[:index])
roles = argv[index + 1:]
deleted = delete_roles(roles, noop=cfg.CONF.dryrun)
if len(deleted):
_print_names("Deleted", deleted)

View File

@ -0,0 +1,71 @@
#!/usr/bin/env python
#
# Copyright 2015 Red Hat
#
# 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.
from __future__ import print_function
import sys
from tuskar.common.exception import OvercloudRoleInUse
from tuskar.manager.plan import PlansManager
from tuskar.storage.exceptions import UnknownUUID
from tuskar.storage.stores import DeploymentPlanStore
from tuskar.storage.stores import TemplateStore
from tuskar.templates import parser
def _check_roles_exist(role_ids):
store = TemplateStore()
for i in role_ids:
try:
store.retrieve(i)
except UnknownUUID:
sys.stderr.write("No role with id %s " % i)
raise
def _check_roles_in_use(role_ids):
manager = PlansManager()
plan_list = manager.list_plans()
plan_store = DeploymentPlanStore()
for plan in plan_list:
db_plan = plan_store.retrieve(plan.uuid)
environment = parser.parse_environment(
db_plan.environment_file.contents
)
roles_in_use = (
[role.uuid for role in manager._find_roles(environment)])
intersection = set(roles_in_use) & set(role_ids)
if intersection:
raise OvercloudRoleInUse(name=", ".join(intersection))
def _delete_role(role_id):
TemplateStore().delete(role_id)
def delete_roles(role_ids=None, noop=False):
deleted = []
# if any of the roles are in use, or invalid, do nothing
_check_roles_in_use(role_ids)
_check_roles_exist(role_ids)
if noop:
role_ids.append("No deletions, dryrun")
return role_ids
else:
for i in role_ids:
_delete_role(i)
deleted.append(i)
return deleted

View File

@ -0,0 +1,37 @@
# -*- encoding: utf-8 -*-
#
# 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.
from mock import call
from mock import patch
from tuskar.cmd import delete_roles
from tuskar.tests.base import TestCase
class DeleteRoleTests(TestCase):
CMD = """ tuskar-delete-roles --dryrun """
UUIDS = """ 3 4 5 """
@patch('tuskar.storage.stores.TemplateStore.retrieve', return_value="boo")
@patch('tuskar.cmd.delete_roles._print_names')
def test_main(self, mock_print, mock_read):
main_args = "%s --uuids %s" % (self.CMD, self.UUIDS)
expected_res = ['3', '4', '5', 'No deletions, dryrun']
# test
delete_roles.main(argv=(main_args).split())
# verify
self.assertEqual([call('Deleted', expected_res)],
mock_print.call_args_list)