From 76a1e23df6b5d4731364be8819617a44b244fb22 Mon Sep 17 00:00:00 2001 From: Boris Pavlovic Date: Fri, 28 Jul 2017 20:26:34 -0700 Subject: [PATCH] [plugins] Introduce @ syntax Simplify and unify full naming of plugins The new logic is pretty strightforward and simple to understand: 1) Full name provided -> Try to find exact match or raise NotFound 2) Only name provided -> Finds all plugins with exact name match: A) if one found -> return it B) if multiple found -> raise error MultiMatch with infomration of platforms c) if none found -> return error This approach is going to force people to be explicit about platform when they use multiple platforms in same task if there are name colisions However, it won't be redunant in case when you are using one platform and don't want to explicitly specify it. Auto-magic discovering of platform should be disabled because: 1) it's unclear how it works and hard to explain which is very bad 2) is going to produce random limitations and unexpected behaviors One of example is if we decided to write large libs for: HTTP, DNS, FTP, and other kind of scenarios and context and have separated platforms for them e.g. @http, @dns, @ftp, .... they are going to be run against "default" platform which doesn't contain any information however they are not @default platform Change-Id: I8ae5369bcf5ef3aba0fa39a95d8c40cf75edb4bf --- rally/plugins/openstack/context/keystone/users.py | 9 ++++++--- rally/plugins/openstack/credential.py | 4 ++++ rally/plugins/openstack/scenario.py | 8 ++++++-- rally/plugins/openstack/validators.py | 4 ++-- tests/unit/fakes.py | 6 ++++++ tests/unit/plugins/openstack/test_validators.py | 11 ++++++----- 6 files changed, 30 insertions(+), 12 deletions(-) diff --git a/rally/plugins/openstack/context/keystone/users.py b/rally/plugins/openstack/context/keystone/users.py index a39f27ab..d16083ec 100644 --- a/rally/plugins/openstack/context/keystone/users.py +++ b/rally/plugins/openstack/context/keystone/users.py @@ -110,9 +110,12 @@ class UserGenerator(context.Context): super(UserGenerator, self).__init__(context) deployment = objects.Deployment.get(context["task"]["deployment_uuid"]) - existing_users = deployment.get_credentials_for("openstack")["users"] - if existing_users and not (set(self.config) - {"user_choice_method"}): - self.existing_users = existing_users + creds = deployment.get_credentials_for("openstack") + if creds.get("admin"): + context["admin"] = {"credential": creds["admin"]} + + if creds["users"] and not (set(self.config) - {"user_choice_method"}): + self.existing_users = creds["users"] else: self.existing_users = [] self.credential = context["admin"]["credential"] diff --git a/rally/plugins/openstack/credential.py b/rally/plugins/openstack/credential.py index 4c6e461c..6db45a5e 100644 --- a/rally/plugins/openstack/credential.py +++ b/rally/plugins/openstack/credential.py @@ -91,6 +91,10 @@ class OpenStackCredential(credential.Credential): for stype, sname in self.clients().services().items()], key=lambda s: s["name"]) + @classmethod + def get_validation_context(cls): + return {"users@openstack": {}} + def clients(self, api_info=None): return osclients.Clients(self, api_info=api_info, cache=self._clients_cache) diff --git a/rally/plugins/openstack/scenario.py b/rally/plugins/openstack/scenario.py index d30fefd8..5a37e835 100644 --- a/rally/plugins/openstack/scenario.py +++ b/rally/plugins/openstack/scenario.py @@ -18,7 +18,9 @@ import random from oslo_config import cfg from osprofiler import profiler +from rally.common.plugin import plugin from rally import osclients +from rally.task import context from rally.task import scenario configure = functools.partial(scenario.configure, platform="openstack") @@ -26,6 +28,8 @@ configure = functools.partial(scenario.configure, platform="openstack") CONF = cfg.CONF +@context.add_default_context("users@openstack", {}) +@plugin.default_meta(inherit=False) class OpenStackScenario(scenario.Scenario): """Base class for all OpenStack scenarios.""" @@ -33,8 +37,8 @@ class OpenStackScenario(scenario.Scenario): super(OpenStackScenario, self).__init__(context) if context: api_info = {} - if "api_versions" in context.get("config", {}): - api_versions = context["config"]["api_versions"] + if "api_versions@openstack" in context.get("config", {}): + api_versions = context["config"]["api_versions@openstack"] for service in api_versions: api_info[service] = { "version": api_versions[service].get("version"), diff --git a/rally/plugins/openstack/validators.py b/rally/plugins/openstack/validators.py index 4a3d2f74..6234493e 100644 --- a/rally/plugins/openstack/validators.py +++ b/rally/plugins/openstack/validators.py @@ -406,7 +406,7 @@ class RequiredServicesValidator(validation.Validator): # NOTE(andreykurilin): validator should ignore services configured # via context(a proper validation should be in context) service_config = config.get("context", {}).get( - "api_versions", {}).get(service, {}) + "api_versions@openstack", {}).get(service, {}) if (service not in available_services and not ("service_type" in service_config or @@ -531,7 +531,7 @@ class RequiredAPIVersionsValidator(validation.Validator): else: used_version = config.get( "context", {}).get( - "api_versions", {}).get( + "api_versions@openstack", {}).get( self.component, {}).get( "version", getattr( clients, self.component).choose_version()) diff --git a/tests/unit/fakes.py b/tests/unit/fakes.py index 0f0f9b54..6d4803a4 100644 --- a/tests/unit/fakes.py +++ b/tests/unit/fakes.py @@ -1857,6 +1857,12 @@ class FakeDeployment(dict): def get_credentials_for(self, namespace): return self["credentials"][namespace][0] + def verify_connections(self): + pass + + def get_validation_context(self): + return {} + class FakeTask(dict, object): diff --git a/tests/unit/plugins/openstack/test_validators.py b/tests/unit/plugins/openstack/test_validators.py index 975b1f14..292bb70b 100644 --- a/tests/unit/plugins/openstack/test_validators.py +++ b/tests/unit/plugins/openstack/test_validators.py @@ -43,7 +43,7 @@ config = dict(args={"image": {"id": "fake_id", "foo_image": {"id": "fake_image_id"} }, context={"images": {"image_name": "foo_image"}, - "api_versions": mock.MagicMock()} + "api_versions@openstack": mock.MagicMock()} ) @@ -534,7 +534,7 @@ class RequiredServicesValidatorTestCase(test.TestCase): def test_validator(self): - self.config["context"]["api_versions"].get = mock.Mock( + self.config["context"]["api_versions@openstack"].get = mock.Mock( return_value={consts.Service.KEYSTONE: "service_type"}) clients = self.credentials["openstack"]["admin"].clients() @@ -575,7 +575,7 @@ class RequiredServicesValidatorTestCase(test.TestCase): def test_validator_wrong_service(self): - self.config["context"]["api_versions"].get = mock.Mock( + self.config["context"]["api_versions@openstack"].get = mock.Mock( return_value={consts.Service.KEYSTONE: "service_type", consts.Service.NOVA: "service_name"}) @@ -761,7 +761,7 @@ class RequiredAPIVersionsValidatorTestCase(test.TestCase): "credential"].clients() clients.nova.choose_version.return_value = nova - config = {"context": {"api_versions": {}}} + config = {"context": {"api_versions@openstack": {}}} result = validator.validate(config, self.credentials, None, None) @@ -779,7 +779,8 @@ class RequiredAPIVersionsValidatorTestCase(test.TestCase): validator = validators.RequiredAPIVersionsValidator("nova", [version]) - config = {"context": {"api_versions": {"nova": {"version": 2}}}} + config = { + "context": {"api_versions@openstack": {"nova": {"version": 2}}}} result = validator.validate(config, self.credentials, None, None)