diff --git a/rally/plugins/openstack/context/network/networks.py b/rally/plugins/openstack/context/network/networks.py index 28da6144ea..2ee5d387dd 100644 --- a/rally/plugins/openstack/context/network/networks.py +++ b/rally/plugins/openstack/context/network/networks.py @@ -80,11 +80,12 @@ class Network(context.Context): for i in range(self.config["networks_per_tenant"]): # NOTE(amaretskiy): add_router and subnets_num take effect # for Neutron only. + network_create_args = self.config["network_create_args"].copy() network = net_wrapper.create_network( tenant_id, add_router=True, subnets_num=self.config["subnets_per_network"], - network_create_args=self.config["network_create_args"]) + network_create_args=network_create_args) self.context["tenants"][tenant_id]["networks"].append(network) @logging.log_task_wrapper(LOG.info, _("Exit context: `network`")) diff --git a/rally/task/context.py b/rally/task/context.py index 051040f1c3..030eb61f6a 100644 --- a/rally/task/context.py +++ b/rally/task/context.py @@ -71,10 +71,22 @@ class Context(plugin.Plugin, functional.FunctionalMixin, CONFIG_SCHEMA = {} def __init__(self, ctx): - self.config = ctx.get("config", {}).get(self.get_name(), {}) - if hasattr(self, "DEFAULT_CONFIG"): - for key, value in self.DEFAULT_CONFIG.items(): - self.config.setdefault(key, value) + config = ctx.get("config", {}).get(self.get_name(), {}) + # NOTE(amaretskiy): self.config is a constant data and must be + # immutable or write-protected type to prevent + # unexpected changes in runtime + if type(config) == dict: + if hasattr(self, "DEFAULT_CONFIG"): + for key, value in self.DEFAULT_CONFIG.items(): + config.setdefault(key, value) + self.config = utils.LockedDict(config) + elif type(config) == list: + self.config = tuple(config) + else: + # NOTE(amaretskiy): It is improbable that config can be a None, + # number, boolean or even string, + # however we handle this + self.config = config self.context = ctx self.task = self.context.get("task", {}) diff --git a/tests/unit/plugins/openstack/context/ceilometer/test_samples.py b/tests/unit/plugins/openstack/context/ceilometer/test_samples.py index 68c548a261..1295869351 100644 --- a/tests/unit/plugins/openstack/context/ceilometer/test_samples.py +++ b/tests/unit/plugins/openstack/context/ceilometer/test_samples.py @@ -57,14 +57,14 @@ class CeilometerSampleGeneratorTestCase(test.TestCase): "resources_per_tenant": resources_per_tenant, "samples_per_resource": samples_per_resource, "timestamp_interval": 60, - "metadata_list": [ + "metadata_list": ( {"status": "active", "name": "fake_resource", "deleted": "False", "created_at": "2015-09-04T12:34:19.000000"}, {"status": "not_active", "name": "fake_resource_1", "deleted": "False", - "created_at": "2015-09-10T06:55:12.000000"} - ] + "created_at": "2015-09-10T06:55:12.000000"}, + ) } }, "admin": { @@ -86,15 +86,15 @@ class CeilometerSampleGeneratorTestCase(test.TestCase): "counter_volume": 1.0, "resources_per_tenant": 5, "samples_per_resource": 5, - "timestamp_intervals": 60, - "metadata_list": [ + "timestamp_interval": 60, + "metadata_list": ( {"status": "active", "name": "fake_resource", "deleted": "False", "created_at": "2015-09-04T12:34:19.000000"}, {"status": "not_active", "name": "fake_resource_1", "deleted": "False", - "created_at": "2015-09-10T06:55:12.000000"} - ] + "created_at": "2015-09-10T06:55:12.000000"}, + ) } } diff --git a/tests/unit/plugins/openstack/context/cleanup/test_admin.py b/tests/unit/plugins/openstack/context/cleanup/test_admin.py index 35a2be9756..50b044e8cb 100644 --- a/tests/unit/plugins/openstack/context/cleanup/test_admin.py +++ b/tests/unit/plugins/openstack/context/cleanup/test_admin.py @@ -61,7 +61,7 @@ class AdminCleanupTestCase(test.TestCase): admin_cleanup.setup() admin_cleanup.cleanup() - mock_find_resource_managers.assert_called_once_with(["a", "b"], True) + mock_find_resource_managers.assert_called_once_with(("a", "b"), True) mock_seek_and_destroy.assert_has_calls([ mock.call( mock_find_resource_managers.return_value[0], @@ -104,7 +104,7 @@ class AdminCleanupTestCase(test.TestCase): admin_cleanup.setup() admin_cleanup.cleanup() - mock_find_resource_managers.assert_called_once_with(["a", "b"], True) + mock_find_resource_managers.assert_called_once_with(("a", "b"), True) mock_seek_and_destroy.assert_has_calls([ mock.call( mock_find_resource_managers.return_value[0], diff --git a/tests/unit/plugins/openstack/context/cleanup/test_user.py b/tests/unit/plugins/openstack/context/cleanup/test_user.py index 3475e3cfc3..f94adbfef2 100644 --- a/tests/unit/plugins/openstack/context/cleanup/test_user.py +++ b/tests/unit/plugins/openstack/context/cleanup/test_user.py @@ -60,7 +60,7 @@ class UserCleanupTestCase(test.TestCase): admin_cleanup.setup() admin_cleanup.cleanup() - mock_find_resource_managers.assert_called_once_with(["a", "b"], False) + mock_find_resource_managers.assert_called_once_with(("a", "b"), False) mock_seek_and_destroy.assert_has_calls([ mock.call( diff --git a/tests/unit/plugins/openstack/context/keystone/test_users.py b/tests/unit/plugins/openstack/context/keystone/test_users.py index 881d4f8ebf..c76872d3b6 100644 --- a/tests/unit/plugins/openstack/context/keystone/test_users.py +++ b/tests/unit/plugins/openstack/context/keystone/test_users.py @@ -223,8 +223,8 @@ class UserGeneratorTestCase(test.ScenarioTestCase): @mock.patch("%s.keystone" % CTX) def test__create_tenants(self, mock_keystone): + self.context["config"]["users"]["tenants"] = 1 user_generator = users.UserGenerator(self.context) - user_generator.config["tenants"] = 1 tenants = user_generator._create_tenants() self.assertEqual(1, len(tenants)) id, tenant = tenants.popitem() @@ -232,10 +232,10 @@ class UserGeneratorTestCase(test.ScenarioTestCase): @mock.patch("%s.keystone" % CTX) def test__create_users(self, mock_keystone): + self.context["config"]["users"]["users_per_tenant"] = 2 user_generator = users.UserGenerator(self.context) user_generator.context["tenants"] = {"t1": {"id": "t1", "name": "t1"}, "t2": {"id": "t2", "name": "t2"}} - user_generator.config["users_per_tenant"] = 2 users_ = user_generator._create_users() self.assertEqual(4, len(users_)) for user in users_: diff --git a/tests/unit/plugins/openstack/context/manila/test_manila_share_networks.py b/tests/unit/plugins/openstack/context/manila/test_manila_share_networks.py index 5f0ce4349f..c71e72b07b 100644 --- a/tests/unit/plugins/openstack/context/manila/test_manila_share_networks.py +++ b/tests/unit/plugins/openstack/context/manila/test_manila_share_networks.py @@ -70,7 +70,7 @@ class ManilaSampleGeneratorTestCase(test.TestCase): inst = manila_share_networks.ManilaShareNetworks(context) self.assertEqual( - context["config"][consts.SHARE_NETWORKS_CONTEXT_NAME], + {"foo": "bar", "share_networks": {}, "use_share_networks": False}, inst.config) self.assertIn( rally_consts.JSON_SCHEMA, inst.CONFIG_SCHEMA.get("$schema")) @@ -107,11 +107,11 @@ class ManilaSampleGeneratorTestCase(test.TestCase): def test_setup_use_existing_share_networks( self, mock_manila_scenario__list_share_networks, mock_clients): existing_sns = self.existing_sns + expected_ctxt = copy.deepcopy(self.ctxt_use_existing) inst = manila_share_networks.ManilaShareNetworks( self.ctxt_use_existing) mock_manila_scenario__list_share_networks.return_value = ( self.existing_sns) - expected_ctxt = copy.deepcopy(self.ctxt_use_existing) expected_ctxt.update({ "delete_share_networks": False, "tenants": { diff --git a/tests/unit/plugins/openstack/context/neutron/test_existing_network.py b/tests/unit/plugins/openstack/context/neutron/test_existing_network.py index c98a20ce3c..b3a5a21010 100644 --- a/tests/unit/plugins/openstack/context/neutron/test_existing_network.py +++ b/tests/unit/plugins/openstack/context/neutron/test_existing_network.py @@ -25,7 +25,7 @@ class ExistingNetworkTestCase(test.TestCase): def setUp(self): super(ExistingNetworkTestCase, self).setUp() - self.config = mock.MagicMock() + self.config = {"foo": "bar"} self.context = test.get_test_context() self.context.update({ "users": [ diff --git a/tests/unit/plugins/openstack/context/nova/test_servers.py b/tests/unit/plugins/openstack/context/nova/test_servers.py index 009036a267..cd81273287 100644 --- a/tests/unit/plugins/openstack/context/nova/test_servers.py +++ b/tests/unit/plugins/openstack/context/nova/test_servers.py @@ -46,7 +46,8 @@ class ServerGeneratorTestCase(test.ScenarioTestCase): "tenants": self._gen_tenants(tenants_count)}) inst = servers.ServerGenerator(self.context) - self.assertEqual(self.context["config"]["servers"], inst.config) + self.assertEqual({"auto_assign_nic": False, "servers_per_tenant": 5}, + inst.config) @mock.patch("%s.nova.utils.NovaScenario._boot_servers" % SCN, return_value=[ diff --git a/tests/unit/plugins/openstack/context/test_api_versions.py b/tests/unit/plugins/openstack/context/test_api_versions.py index a52cf287aa..3441d2b7d0 100644 --- a/tests/unit/plugins/openstack/context/test_api_versions.py +++ b/tests/unit/plugins/openstack/context/test_api_versions.py @@ -10,8 +10,6 @@ # License for the specific language governing permissions and limitations # under the License. -import copy - import jsonschema import mock @@ -112,16 +110,17 @@ class OpenStackServicesTestCase(test.TestCase): def test_setup_with_service_name(self): self.mock_kc.services.list.return_value = [ utils.Struct(type="computev21", name="NovaV21")] + name = api_versions.OpenStackAPIVersions.get_name() context = { - "config": {api_versions.OpenStackAPIVersions.get_name(): { - "nova": {"service_name": "NovaV21"}}}, + "config": {name: {"nova": {"service_name": "NovaV21"}}}, "admin": {"credential": mock.MagicMock()}, "users": [{"credential": mock.MagicMock()}]} - ctx = api_versions.OpenStackAPIVersions(copy.deepcopy(context)) - + ctx = api_versions.OpenStackAPIVersions(context) ctx.setup() self.mock_kc.service_catalog.get_endpoints.assert_called_once_with() self.mock_kc.services.list.assert_called_once_with() - self.assertEqual("computev21", ctx.config["nova"]["service_type"]) + self.assertEqual( + "computev21", + ctx.context["config"]["api_versions"]["nova"]["service_type"]) diff --git a/tests/unit/task/test_context.py b/tests/unit/task/test_context.py index 460fb52c05..f15d49a6b1 100644 --- a/tests/unit/task/test_context.py +++ b/tests/unit/task/test_context.py @@ -13,7 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. - +import ddt import jsonschema import mock @@ -23,26 +23,39 @@ from tests.unit import fakes from tests.unit import test +@ddt.ddt class BaseContextTestCase(test.TestCase): - def test_init(self): - ctx0 = { - "config": { - "a": 1, - "fake": mock.MagicMock() - }, - "task": mock.MagicMock() - } + @ddt.data({"config": {"bar": "spam"}, "expected": {"bar": "spam"}}, + {"config": {"bar": "spam"}, "expected": {"bar": "spam"}}, + {"config": {}, "expected": {}}, + {"config": None, "expected": None}, + {"config": 42, "expected": 42}, + {"config": "foo str", "expected": "foo str"}, + {"config": [], "expected": ()}, + {"config": [11, 22, 33], "expected": (11, 22, 33)}) + @ddt.unpack + def test_init(self, config, expected): + ctx = {"config": {"foo": 42, "fake": config}, "task": "foo_task"} + ins = fakes.FakeContext(ctx) + self.assertEqual(ins.config, expected) + self.assertEqual(ins.task, "foo_task") + self.assertEqual(ins.context, ctx) - ctx = fakes.FakeContext(ctx0) - self.assertEqual(ctx.config, ctx0["config"]["fake"]) - self.assertEqual(ctx.task, ctx0["task"]) - self.assertEqual(ctx.context, ctx0) + def test_init_with_default_config(self): + @context.configure(name="foo", order=1) + class FooContext(fakes.FakeContext): + DEFAULT_CONFIG = {"alpha": "beta", "delta": "gamma"} + + ctx = {"config": {"foo": {"ab": "cd"}, "bar": 42}, "task": "foo_task"} + ins = FooContext(ctx) + self.assertEqual({"ab": "cd", "alpha": "beta", "delta": "gamma"}, + ins.config) def test_init_empty_context(self): ctx0 = { "task": mock.MagicMock(), - "config": {"fake": "test"} + "config": {"fake": {"foo": 42}} } ctx = fakes.FakeContext(ctx0) self.assertEqual(ctx.config, ctx0["config"]["fake"])