Add root-actions int-tests
Add new scenario integration tests for root-related actions. Closes-Bug: 1529965 Change-Id: Id317eacc5a028317d07a70c183173099d3125a43
This commit is contained in:
parent
fac6e76b54
commit
d1bb391d30
|
@ -42,6 +42,7 @@ from trove.tests.scenario.groups import instance_create_group
|
|||
from trove.tests.scenario.groups import instance_delete_group
|
||||
from trove.tests.scenario.groups import negative_cluster_actions_group
|
||||
from trove.tests.scenario.groups import replication_group
|
||||
from trove.tests.scenario.groups import root_actions_group
|
||||
from trove.tests.scenario.groups import user_actions_group
|
||||
|
||||
|
||||
|
@ -157,6 +158,9 @@ instance_actions_groups.extend([instance_actions_group.GROUP])
|
|||
replication_groups = list(instance_create_groups)
|
||||
replication_groups.extend([replication_group.GROUP])
|
||||
|
||||
root_actions_groups = list(instance_create_groups)
|
||||
root_actions_groups.extend([root_actions_group.GROUP])
|
||||
|
||||
user_actions_groups = list(instance_create_groups)
|
||||
user_actions_groups.extend([user_actions_group.GROUP])
|
||||
|
||||
|
@ -173,6 +177,7 @@ register(["guest_log"], guest_log_groups)
|
|||
register(["instance", "instance_actions"], instance_actions_groups)
|
||||
register(["instance_create"], instance_create_groups)
|
||||
register(["replication"], replication_groups)
|
||||
register(["root"], root_actions_groups)
|
||||
register(["user"], user_actions_groups)
|
||||
|
||||
# Register: Datastore based groups
|
||||
|
@ -181,21 +186,22 @@ register(["db2_supported"], common_groups,
|
|||
database_actions_groups, user_actions_groups)
|
||||
register(["cassandra_supported"], common_groups,
|
||||
backup_groups, configuration_groups)
|
||||
register(["couchbase_supported"], common_groups, backup_groups)
|
||||
register(["couchbase_supported"], common_groups, backup_groups,
|
||||
root_actions_groups)
|
||||
register(["couchdb_supported"], common_groups)
|
||||
register(["postgresql_supported"], common_groups,
|
||||
backup_groups, database_actions_groups, configuration_groups,
|
||||
user_actions_groups)
|
||||
root_actions_groups, user_actions_groups)
|
||||
register(["mariadb_supported", "mysql_supported", "percona_supported"],
|
||||
common_groups,
|
||||
backup_groups, configuration_groups, database_actions_groups,
|
||||
replication_groups, user_actions_groups)
|
||||
replication_groups, root_actions_groups, user_actions_groups)
|
||||
register(["mongodb_supported"], common_groups,
|
||||
backup_groups, cluster_actions_groups, configuration_groups,
|
||||
database_actions_groups, user_actions_groups)
|
||||
database_actions_groups, root_actions_groups, user_actions_groups)
|
||||
register(["pxc_supported"], common_groups,
|
||||
cluster_actions_groups)
|
||||
cluster_actions_groups, root_actions_groups)
|
||||
register(["redis_supported"], common_groups,
|
||||
backup_groups, replication_groups)
|
||||
register(["vertica_supported"], common_groups,
|
||||
cluster_actions_groups)
|
||||
cluster_actions_groups, root_actions_groups)
|
||||
|
|
|
@ -21,6 +21,7 @@ from trove.tests.scenario.groups import database_actions_group
|
|||
from trove.tests.scenario.groups import instance_actions_group
|
||||
from trove.tests.scenario.groups import instance_create_group
|
||||
from trove.tests.scenario.groups import replication_group
|
||||
from trove.tests.scenario.groups import root_actions_group
|
||||
from trove.tests.scenario.groups.test_group import TestGroup
|
||||
from trove.tests.scenario.groups import user_actions_group
|
||||
|
||||
|
@ -35,6 +36,7 @@ GROUP = "scenario.instance_delete_group"
|
|||
database_actions_group.GROUP,
|
||||
instance_actions_group.GROUP,
|
||||
replication_group.GROUP,
|
||||
root_actions_group.GROUP,
|
||||
user_actions_group.GROUP])
|
||||
class InstanceDeleteGroup(TestGroup):
|
||||
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
# Copyright 2015 Tesora Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 proboscis import test
|
||||
|
||||
from trove.tests.scenario.groups import instance_create_group
|
||||
from trove.tests.scenario.groups.test_group import TestGroup
|
||||
|
||||
|
||||
GROUP = "scenario.root_actions_group"
|
||||
|
||||
|
||||
@test(depends_on_groups=[instance_create_group.GROUP], groups=[GROUP])
|
||||
class RootActionsGroup(TestGroup):
|
||||
|
||||
def __init__(self):
|
||||
super(RootActionsGroup, self).__init__(
|
||||
'root_actions_runners', 'RootActionsRunner')
|
||||
self.backup_runner = self.get_runner(
|
||||
'backup_runners', 'BackupRunner')
|
||||
|
||||
@test
|
||||
def check_root_never_enabled(self):
|
||||
"""Check the root has never been enabled on the instance."""
|
||||
self.test_runner.run_check_root_never_enabled()
|
||||
|
||||
@test(depends_on=[check_root_never_enabled])
|
||||
def disable_root_before_enabled(self):
|
||||
"""Ensure disable fails if root was never enabled."""
|
||||
self.test_runner.run_disable_root_before_enabled()
|
||||
|
||||
@test(depends_on=[check_root_never_enabled],
|
||||
runs_after=[disable_root_before_enabled])
|
||||
def enable_root_no_password(self):
|
||||
"""Enable root (without specifying a password)."""
|
||||
self.test_runner.run_enable_root_no_password()
|
||||
|
||||
@test(depends_on=[enable_root_no_password])
|
||||
def check_root_enabled(self):
|
||||
"""Check the root is now enabled."""
|
||||
self.test_runner.run_check_root_enabled()
|
||||
|
||||
@test(depends_on=[check_root_enabled])
|
||||
def backup_root_enabled_instance(self):
|
||||
"""Backup the root-enabled instance."""
|
||||
self.backup_runner.run_backup_create()
|
||||
self.backup_runner.run_backup_create_completed()
|
||||
|
||||
@test(depends_on=[backup_root_enabled_instance])
|
||||
def restore_root_enabled_instance(self):
|
||||
"""Restore the root-enabled instance."""
|
||||
self.backup_runner.run_restore_from_backup()
|
||||
|
||||
@test(depends_on=[check_root_enabled])
|
||||
def delete_root(self):
|
||||
"""Ensure an attempt to delete the root user fails."""
|
||||
self.test_runner.run_delete_root()
|
||||
|
||||
@test(depends_on=[check_root_never_enabled],
|
||||
runs_after=[delete_root])
|
||||
def enable_root_with_password(self):
|
||||
"""Enable root (with a given password)."""
|
||||
self.test_runner.run_enable_root_with_password()
|
||||
|
||||
@test(depends_on=[enable_root_with_password])
|
||||
def check_root_still_enabled(self):
|
||||
"""Check the root is still enabled."""
|
||||
self.test_runner.run_check_root_still_enabled()
|
||||
|
||||
@test(depends_on=[check_root_enabled],
|
||||
runs_after=[check_root_still_enabled])
|
||||
def disable_root(self):
|
||||
"""Disable root."""
|
||||
self.test_runner.run_disable_root()
|
||||
|
||||
@test(depends_on=[disable_root])
|
||||
def check_root_still_enabled_after_disable(self):
|
||||
"""Check the root is still marked as enabled after disable."""
|
||||
self.test_runner.run_check_root_still_enabled_after_disable()
|
||||
|
||||
@test(depends_on=[restore_root_enabled_instance],
|
||||
runs_after=[check_root_still_enabled_after_disable])
|
||||
def wait_for_restored_instance(self):
|
||||
"""Wait until restoring a root-enabled instance completes."""
|
||||
self.backup_runner.run_restore_from_backup_completed()
|
||||
|
||||
@test(depends_on=[wait_for_restored_instance])
|
||||
def check_root_enabled_after_restore(self):
|
||||
"""Check the root is also enabled on the restored instance."""
|
||||
instance_id = self.backup_runner.restore_instance_id
|
||||
self.test_runner.run_check_root_enabled_after_restore(instance_id)
|
|
@ -419,3 +419,11 @@ class TestHelper(object):
|
|||
restart of the datastore.
|
||||
"""
|
||||
return False
|
||||
|
||||
##############
|
||||
# Root related
|
||||
##############
|
||||
def get_valid_root_password(self):
|
||||
"""Return a valid password that can be used by a 'root' user.
|
||||
"""
|
||||
return "RootTestPass"
|
||||
|
|
|
@ -77,6 +77,12 @@ class InstanceCreateRunner(TestRunner):
|
|||
self, with_dbs=True, with_users=True, configuration_id=None,
|
||||
expected_states=['BUILD', 'ACTIVE'], expected_http_code=200,
|
||||
create_helper_user=True):
|
||||
if self.is_using_existing_instance:
|
||||
# The user requested to run the tests using an existing instance.
|
||||
# We therefore skip any scenarios that involve creating new
|
||||
# test instances.
|
||||
raise SkipTest("Using an existing instance.")
|
||||
|
||||
name = self.instance_info.name + '_init'
|
||||
flavor = self._get_instance_flavor()
|
||||
trove_volume_size = CONFIG.get('trove_volume_size', 1)
|
||||
|
@ -87,9 +93,6 @@ class InstanceCreateRunner(TestRunner):
|
|||
if configuration_id:
|
||||
self.init_config_group_id = configuration_id
|
||||
|
||||
if self.is_using_existing_instance:
|
||||
raise SkipTest("Using existing instance.")
|
||||
|
||||
if (self.init_inst_dbs or self.init_inst_users or
|
||||
self.init_config_group_id):
|
||||
info = self.assert_instance_create(
|
||||
|
@ -230,8 +233,6 @@ class InstanceCreateRunner(TestRunner):
|
|||
instances = [self.instance_info.id]
|
||||
if self.init_inst_id:
|
||||
instances.append(self.init_inst_id)
|
||||
if self.is_using_existing_instance:
|
||||
expected_states = ['ACTIVE']
|
||||
self.assert_all_instance_states(instances, expected_states)
|
||||
|
||||
def run_add_initialized_instance_data(self):
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
# Copyright 2015 Tesora Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 proboscis import SkipTest
|
||||
|
||||
from trove.tests.scenario.runners.test_runners import TestRunner
|
||||
from troveclient.compat import exceptions
|
||||
|
||||
|
||||
class RootActionsRunner(TestRunner):
|
||||
|
||||
def __init__(self):
|
||||
self.current_root_creds = None
|
||||
super(RootActionsRunner, self).__init__()
|
||||
|
||||
def run_check_root_never_enabled(self, expected_http_code=200):
|
||||
self.assert_root_disabled(self.instance_info.id, expected_http_code)
|
||||
|
||||
def assert_root_disabled(self, instance_id, expected_http_code):
|
||||
self._assert_root_state(instance_id, False, expected_http_code,
|
||||
"The root has already been enabled on the "
|
||||
"instance.")
|
||||
|
||||
def _assert_root_state(self, instance_id, expected_state,
|
||||
expected_http_code, message):
|
||||
# The call returns a nameless user object with 'rootEnabled' attribute.
|
||||
response = self.auth_client.root.is_root_enabled(instance_id)
|
||||
self.assert_instance_action(instance_id, None, expected_http_code)
|
||||
actual_state = getattr(response, 'rootEnabled', None)
|
||||
self.assert_equal(expected_state, actual_state, message)
|
||||
|
||||
def run_disable_root_before_enabled(
|
||||
self, expected_exception=exceptions.NotFound,
|
||||
expected_http_code=404):
|
||||
self.assert_root_disable_failure(
|
||||
self.instance_info.id, expected_exception, expected_http_code)
|
||||
|
||||
def assert_root_disable_failure(self, instance_id, expected_exception,
|
||||
expected_http_code):
|
||||
self.assert_raises(expected_exception, expected_http_code,
|
||||
self.auth_client.root.delete, instance_id)
|
||||
|
||||
def run_enable_root_no_password(self, expected_http_code=200):
|
||||
self.current_root_creds = self.assert_root_create(
|
||||
self.instance_info.id, None, expected_http_code)
|
||||
|
||||
def assert_root_create(self, instance_id, root_password,
|
||||
expected_http_code):
|
||||
if root_password:
|
||||
root_creds = self.auth_client.root.create_instance_root(
|
||||
instance_id, root_password)
|
||||
else:
|
||||
root_creds = self.auth_client.root.create(instance_id)
|
||||
|
||||
self.assert_instance_action(instance_id, None, expected_http_code)
|
||||
return root_creds
|
||||
|
||||
def run_check_root_enabled(self, expected_http_code=200):
|
||||
self.assert_root_enabled(self.instance_info.id, expected_http_code)
|
||||
|
||||
def assert_root_enabled(self, instance_id, expected_http_code):
|
||||
self._assert_root_state(instance_id, True, expected_http_code,
|
||||
"The root has not been enabled on the "
|
||||
"instance yet.")
|
||||
|
||||
def run_enable_root_with_password(self, expected_http_code=200):
|
||||
password = self.test_helper.get_valid_root_password()
|
||||
self.current_root_creds = self.assert_root_create(
|
||||
self.instance_info.id, password, expected_http_code)
|
||||
|
||||
def run_check_root_still_enabled(self, expected_http_code=200):
|
||||
self.assert_root_enabled(self.instance_info.id, expected_http_code)
|
||||
|
||||
def run_disable_root(self, expected_http_code=200):
|
||||
self.assert_root_disable(self.instance_info.id, expected_http_code)
|
||||
|
||||
def assert_root_disable(self, instance_id, expected_http_code):
|
||||
self.auth_client.root.delete(instance_id)
|
||||
self.assert_instance_action(instance_id, None, expected_http_code)
|
||||
|
||||
def run_check_root_still_enabled_after_disable(
|
||||
self, expected_http_code=200):
|
||||
self.assert_root_enabled(self.instance_info.id, expected_http_code)
|
||||
|
||||
def run_delete_root(self, expected_exception=exceptions.BadRequest,
|
||||
expected_http_code=400):
|
||||
self.assert_root_delete_failure(
|
||||
self.instance_info.id, expected_exception, expected_http_code)
|
||||
|
||||
def assert_root_delete_failure(self, instance_id, expected_exception,
|
||||
expected_http_code):
|
||||
root_user_name = self.current_root_creds[0]
|
||||
self.assert_raises(expected_exception, expected_http_code,
|
||||
self.auth_client.users.delete,
|
||||
instance_id, root_user_name)
|
||||
|
||||
def run_check_root_enabled_after_restore(self, restored_instance_id,
|
||||
expected_http_code=200):
|
||||
if restored_instance_id:
|
||||
self.assert_root_enabled(restored_instance_id, expected_http_code)
|
||||
else:
|
||||
raise SkipTest("No instance with enabled root restored.")
|
||||
|
||||
|
||||
class MysqlRootActionsRunner(RootActionsRunner):
|
||||
|
||||
def run_enable_root_with_password(self):
|
||||
raise SkipTest("Operation is currently not supported.")
|
||||
|
||||
|
||||
class CouchbaseRootActionsRunner(RootActionsRunner):
|
||||
|
||||
def run_disable_root_before_enabled(self):
|
||||
raise SkipTest("Operation is currently not supported.")
|
||||
|
||||
def run_enable_root_with_password(self):
|
||||
raise SkipTest("Operation is currently not supported.")
|
||||
|
||||
def run_disable_root(self):
|
||||
raise SkipTest("Operation is currently not supported.")
|
|
@ -265,7 +265,7 @@ class TestRunner(object):
|
|||
self.fail(str(task.poll_exception()))
|
||||
|
||||
def _assert_instance_states(self, instance_id, expected_states,
|
||||
fast_fail_status='ERROR',
|
||||
fast_fail_status=['ERROR', 'FAILED'],
|
||||
require_all_states=False):
|
||||
"""Keep polling for the expected instance states until the instance
|
||||
acquires either the last or fast-fail state.
|
||||
|
@ -357,10 +357,11 @@ class TestRunner(object):
|
|||
sleep_time=sleep_time, time_out=time_out)
|
||||
|
||||
def _has_status(self, instance_id, status, fast_fail_status=None):
|
||||
fast_fail_status = fast_fail_status or []
|
||||
instance = self.get_instance(instance_id)
|
||||
self.report.log("Polling instance '%s' for state '%s', was '%s'."
|
||||
% (instance_id, status, instance.status))
|
||||
if fast_fail_status and instance.status == fast_fail_status:
|
||||
if instance.status in fast_fail_status:
|
||||
raise RuntimeError("Instance '%s' acquired a fast-fail status: %s"
|
||||
% (instance_id, instance.status))
|
||||
return instance.status == status
|
||||
|
|
Loading…
Reference in New Issue