Make return data of Deployment API serializable

Add method '.to_dict()' which allows converts returned result to
JSON format

Change-Id: Id005d6e224ae9351ad9786b7c2903616acc00ad8
This commit is contained in:
astaroverov 2017-03-07 16:30:53 +03:00
parent 44047515ab
commit df2c1807a3
11 changed files with 130 additions and 64 deletions

View File

@ -46,7 +46,7 @@ LOG = logging.getLogger(__name__)
class _Deployment(object): class _Deployment(object):
@classmethod @classmethod
def create(cls, config, name): def _create(cls, config, name):
"""Create a deployment. """Create a deployment.
:param config: a dict with deployment configuration :param config: a dict with deployment configuration
@ -76,6 +76,10 @@ class _Deployment(object):
deployment.update_credentials(credentials) deployment.update_credentials(credentials)
return deployment return deployment
@classmethod
def create(cls, config, name):
return cls._create(config, name).to_dict()
@classmethod @classmethod
def destroy(cls, deployment): def destroy(cls, deployment):
"""Destroy the deployment. """Destroy the deployment.
@ -133,7 +137,7 @@ class _Deployment(object):
deployment.update_credentials(credentials) deployment.update_credentials(credentials)
@classmethod @classmethod
def get(cls, deployment): def _get(cls, deployment):
"""Get the deployment. """Get the deployment.
:param deployment: UUID or name of the deployment :param deployment: UUID or name of the deployment
@ -141,6 +145,10 @@ class _Deployment(object):
""" """
return objects.Deployment.get(deployment) return objects.Deployment.get(deployment)
@classmethod
def get(cls, deployment):
return cls._get(deployment).to_dict()
@classmethod @classmethod
def service_list(cls, deployment): def service_list(cls, deployment):
"""Get the services list. """Get the services list.
@ -164,10 +172,11 @@ class _Deployment(object):
def check(cls, deployment): def check(cls, deployment):
"""Check keystone authentication and list all available services. """Check keystone authentication and list all available services.
:param deployment: UUID of deployment
:returns: Service list :returns: Service list
""" """
# TODO(astudenov): make this method platform independent # TODO(astudenov): make this method platform independent
creds = deployment.get_credentials_for("openstack") creds = cls._get(deployment).get_credentials_for("openstack")
creds["admin"].verify_connection() creds["admin"].verify_connection()
for user in creds["users"]: for user in creds["users"]:
user.verify_connection() user.verify_connection()

View File

@ -111,7 +111,7 @@ class DeploymentCommands(object):
self.list(api, deployment_list=[deployment]) self.list(api, deployment_list=[deployment])
if do_use: if do_use:
self.use(api, deployment["uuid"]) self.use(api, deployment)
@cliutils.args("--filename", type=str, required=False, metavar="<path>", @cliutils.args("--filename", type=str, required=False, metavar="<path>",
help="Path to the configuration file of the deployment.") help="Path to the configuration file of the deployment.")
@ -206,13 +206,13 @@ class DeploymentCommands(object):
table_rows = [] table_rows = []
deployment = api.deployment.get(deployment) deployment = api.deployment.get(deployment)
creds = deployment.get_credentials_for("openstack")
creds = deployment["credentials"]["openstack"][0]
users = creds["users"] users = creds["users"]
admin = creds["admin"] admin = creds["admin"]
credentials = users + [admin] if admin else users credentials = users + [admin] if admin else users
for ep in credentials: for ep in credentials:
data = ["***" if m == "password" else getattr(ep, m, "") data = ["***" if m == "password" else ep.get(m, "")
for m in headers] for m in headers]
table_rows.append(utils.Struct(**dict(zip(headers, data)))) table_rows.append(utils.Struct(**dict(zip(headers, data))))
cliutils.print_list(table_rows, headers) cliutils.print_list(table_rows, headers)
@ -230,17 +230,12 @@ class DeploymentCommands(object):
# TODO(astudenov): make this method platform independent # TODO(astudenov): make this method platform independent
headers = ["services", "type", "status"] headers = ["services", "type", "status"]
table_rows = [] table_rows = []
try:
deployment = api.deployment.get(deployment) deployment = api.deployment.get(deployment)
except exceptions.DeploymentNotFound:
print(_("Deployment %s is not found.") % deployment)
return(1)
try: try:
services = api.deployment.check(deployment) services = api.deployment.check(deployment["uuid"])
except keystone_exceptions.ConnectionRefused: except keystone_exceptions.ConnectionRefused:
admin = deployment.get_credentials_for("openstack")["admin"] admin = deployment["credentials"]["openstack"][0]["admin"]
print(_("Unable to connect %s.") % admin.auth_url) print(_("Unable to connect %s.") % admin.auth_url)
return(1) return(1)
@ -310,16 +305,16 @@ class DeploymentCommands(object):
""" """
# TODO(astudenov): make this method platform independent # TODO(astudenov): make this method platform independent
try: try:
if not isinstance(deployment, dict):
deployment = api.deployment.get(deployment) deployment = api.deployment.get(deployment)
print("Using deployment: %s" % deployment["uuid"]) print("Using deployment: %s" % deployment["uuid"])
fileutils.update_globals_file("RALLY_DEPLOYMENT", fileutils.update_globals_file("RALLY_DEPLOYMENT",
deployment["uuid"]) deployment["uuid"])
creds = deployment.get_credentials_for("openstack") creds = deployment["credentials"]["openstack"][0]
credential = creds["admin"] or creds["users"][0]
self._update_openrc_deployment_file( self._update_openrc_deployment_file(
deployment["uuid"], credential.to_dict()) deployment["uuid"], creds["admin"] or creds["users"][0])
print("~/.rally/openrc was updated\n\nHINTS:\n" print("~/.rally/openrc was updated\n\nHINTS:\n"
"\n* To use standard OpenStack clients, set up your env by " "\n* To use standard OpenStack clients, set up your env by "
"running:\n\tsource ~/.rally/openrc\n" "running:\n\tsource ~/.rally/openrc\n"

View File

@ -52,6 +52,7 @@ CREDENTIALS_SCHEMA = {
class Deployment(object): class Deployment(object):
"""Represents a deployment object.""" """Represents a deployment object."""
TIME_FORMAT = consts.TimeFormat.ISO8601
def __init__(self, deployment=None, **attributes): def __init__(self, deployment=None, **attributes):
if deployment: if deployment:
@ -68,6 +69,15 @@ class Deployment(object):
return self.get_credentials_for("openstack")[key] return self.get_credentials_for("openstack")[key]
return self.deployment[key] return self.deployment[key]
def to_dict(self):
result = {}
formatters = ["created_at", "completed_at", "started_at", "updated_at"]
for field, value in self.deployment.items():
if field in formatters:
value = value.strftime(self.TIME_FORMAT)
result[field] = value
return result
@staticmethod @staticmethod
def get(deploy): def get(deploy):
return Deployment(db.deployment_get(deploy)) return Deployment(db.deployment_get(deploy))

View File

@ -19,7 +19,7 @@ from rally import consts
class Verification(object): class Verification(object):
"""Represents a verification object.""" """Represents a verification object."""
TIME_FORMAT = consts.TimeFormat.TIME_FORMAT_ISO8601 TIME_FORMAT = consts.TimeFormat.ISO8601
def __init__(self, verification): def __init__(self, verification):
"""Init a verification object. """Init a verification object.

View File

@ -21,7 +21,7 @@ from rally.verification import manager
class Verifier(object): class Verifier(object):
"""Represents a verifier object.""" """Represents a verifier object."""
TIME_FORMAT = consts.TimeFormat.TIME_FORMAT_ISO8601 TIME_FORMAT = consts.TimeFormat.ISO8601
def __init__(self, verifier): def __init__(self, verifier):
"""Init a verifier object. """Init a verifier object.

View File

@ -216,7 +216,7 @@ class _VerificationStatus(utils.ImmutableMixin, utils.EnumMixin):
class _TimeFormat(utils.ImmutableMixin, utils.EnumMixin): class _TimeFormat(utils.ImmutableMixin, utils.EnumMixin):
"""International time formats""" """International time formats"""
TIME_FORMAT_ISO8601 = "%Y-%m-%dT%H:%M:%S%z" ISO8601 = "%Y-%m-%dT%H:%M:%S%z"
TaskStatus = _TaskStatus() TaskStatus = _TaskStatus()

View File

@ -26,7 +26,7 @@ from rally.verification import reporter
SKIP_RE = re.compile("Skipped until Bug: ?(?P<bug_number>\d+) is resolved.") SKIP_RE = re.compile("Skipped until Bug: ?(?P<bug_number>\d+) is resolved.")
LP_BUG_LINK = "https://launchpad.net/bugs/%s" LP_BUG_LINK = "https://launchpad.net/bugs/%s"
TIME_FORMAT = consts.TimeFormat.TIME_FORMAT_ISO8601 TIME_FORMAT = consts.TimeFormat.ISO8601
@reporter.configure("json") @reporter.configure("json")

View File

@ -58,7 +58,7 @@ class TestTaskSamples(unittest.TestCase):
db.CONF, connection="sqlite:///%s/db" % rally.tmp_dir) db.CONF, connection="sqlite:///%s/db" % rally.tmp_dir)
# let's use pre-created users to make TestTaskSamples quicker # let's use pre-created users to make TestTaskSamples quicker
deployment = api.Deployment.get("MAIN") deployment = api._Deployment._get("MAIN")
admin_cred = deployment.get_credentials_for("openstack")["admin"] admin_cred = deployment.get_credentials_for("openstack")["admin"]
ctx = {"admin": {"credential": admin_cred}, ctx = {"admin": {"credential": admin_cred},
@ -69,6 +69,7 @@ class TestTaskSamples(unittest.TestCase):
config = deployment["config"] config = deployment["config"]
os_creds = config["creds"]["openstack"] os_creds = config["creds"]["openstack"]
user = copy.copy(os_creds["admin"]) user = copy.copy(os_creds["admin"])
user["username"] = ctx["users"][0]["credential"].username user["username"] = ctx["users"][0]["credential"].username
user["password"] = ctx["users"][0]["credential"].password user["password"] = ctx["users"][0]["credential"].password

View File

@ -132,7 +132,7 @@ class DeploymentCommandsTestCase(test.TestCase):
mock_deployment_commands_list.assert_called_once_with( mock_deployment_commands_list.assert_called_once_with(
self.fake_api, deployment_list=[{"uuid": "uuid"}]) self.fake_api, deployment_list=[{"uuid": "uuid"}])
mock_deployment_commands_use.assert_called_once_with( mock_deployment_commands_use.assert_called_once_with(
self.fake_api, "uuid") self.fake_api, self.fake_api.deployment.create.return_value)
def test_recreate(self): def test_recreate(self):
deployment_id = "43924f8b-9371-4152-af9f-4cf02b4eced4" deployment_id = "43924f8b-9371-4152-af9f-4cf02b4eced4"
@ -237,18 +237,17 @@ class DeploymentCommandsTestCase(test.TestCase):
@mock.patch("rally.cli.commands.deployment.utils.Struct") @mock.patch("rally.cli.commands.deployment.utils.Struct")
def test_show(self, mock_struct, mock_print_list): def test_show(self, mock_struct, mock_print_list):
deployment_id = "b1a6153e-a314-4cb3-b63b-cf08c1a416c3" deployment_id = "b1a6153e-a314-4cb3-b63b-cf08c1a416c3"
value = { value = {"admin": {"auth_url": "url",
"admin": fakes.fake_credential( "username": "u",
auth_url="url", "password": "p",
username="u", "tenant_name": "t",
password="p", "region_name": "r",
tenant_name="t", "endpoint_type": consts.EndpointType.INTERNAL},
region_name="r", "users": []}
endpoint_type=consts.EndpointType.INTERNAL), deployment = self.fake_api.deployment.get
"users": [] deployment.return_value = {"credentials": {"openstack": [
} {"admin": value["admin"],
deployment = self.fake_api.deployment.get.return_value "users": []}]}}
deployment.get_credentials_for.return_value = value
self.deployment.show(self.fake_api, deployment_id) self.deployment.show(self.fake_api, deployment_id)
self.fake_api.deployment.get.assert_called_once_with(deployment_id) self.fake_api.deployment.get.assert_called_once_with(deployment_id)
@ -273,12 +272,12 @@ class DeploymentCommandsTestCase(test.TestCase):
deployment_id = "593b683c-4b16-4b2b-a56b-e162bd60f10b" deployment_id = "593b683c-4b16-4b2b-a56b-e162bd60f10b"
self.fake_api.deployment.get.return_value = fakes.FakeDeployment( self.fake_api.deployment.get.return_value = fakes.FakeDeployment(
uuid=deployment_id, uuid=deployment_id,
admin=fakes.fake_credential(**{"auth_url": "fake_auth_url", admin={"auth_url": "fake_auth_url",
"username": "fake_username", "username": "fake_username",
"password": "fake_password", "password": "fake_password",
"tenant_name": "fake_tenant_name", "tenant_name": "fake_tenant_name",
"endpoint": "fake_endpoint", "endpoint": "fake_endpoint",
"region_name": None})) "region_name": None})
with mock.patch("rally.cli.commands.deployment.open", mock.mock_open(), with mock.patch("rally.cli.commands.deployment.open", mock.mock_open(),
create=True) as mock_file: create=True) as mock_file:
@ -310,7 +309,7 @@ class DeploymentCommandsTestCase(test.TestCase):
self.fake_api.deployment.get.return_value = fakes.FakeDeployment( self.fake_api.deployment.get.return_value = fakes.FakeDeployment(
uuid=deployment_id, uuid=deployment_id,
admin=fakes.fake_credential(**{ admin={
"auth_url": "http://localhost:5000/v3", "auth_url": "http://localhost:5000/v3",
"username": "fake_username", "username": "fake_username",
"password": "fake_password", "password": "fake_password",
@ -318,7 +317,7 @@ class DeploymentCommandsTestCase(test.TestCase):
"endpoint": "fake_endpoint", "endpoint": "fake_endpoint",
"region_name": None, "region_name": None,
"user_domain_name": "fake_user_domain", "user_domain_name": "fake_user_domain",
"project_domain_name": "fake_project_domain"})) "project_domain_name": "fake_project_domain"})
with mock.patch("rally.cli.commands.deployment.open", mock.mock_open(), with mock.patch("rally.cli.commands.deployment.open", mock.mock_open(),
create=True) as mock_file: create=True) as mock_file:
@ -360,7 +359,7 @@ class DeploymentCommandsTestCase(test.TestCase):
mock_update_globals_file.assert_called_once_with( mock_update_globals_file.assert_called_once_with(
envutils.ENV_DEPLOYMENT, "fake_uuid") envutils.ENV_DEPLOYMENT, "fake_uuid")
mock__update_openrc_deployment_file.assert_called_once_with( mock__update_openrc_deployment_file.assert_called_once_with(
"fake_uuid", {"foo": "fake_credentials"}) "fake_uuid", fake_credential)
def test_deployment_not_found(self): def test_deployment_not_found(self):
deployment_id = "e87e4dca-b515-4477-888d-5f6103f13b42" deployment_id = "e87e4dca-b515-4477-888d-5f6103f13b42"
@ -374,33 +373,30 @@ class DeploymentCommandsTestCase(test.TestCase):
sample_credential = fakes.fake_credential( sample_credential = fakes.fake_credential(
auth_url="http://192.168.1.1:5000/v2.0/", auth_url="http://192.168.1.1:5000/v2.0/",
username="admin", password="adminpass") username="admin", password="adminpass")
deployment = {"admin": sample_credential, deployment = {"uuid": deployment_id,
"users": [sample_credential]} "credentials": {"openstack": [
{"admin": sample_credential,
"users": [sample_credential]}]}}
self.fake_api.deployment.get.return_value = deployment self.fake_api.deployment.get.return_value = deployment
self.fake_api.deployment.check.return_value = {} self.fake_api.deployment.check.return_value = {}
self.deployment.check(self.fake_api, deployment_id) self.deployment.check(self.fake_api, deployment_id)
self.fake_api.deployment.get.assert_called_once_with(deployment_id) self.fake_api.deployment.get.assert_called_once_with(deployment_id)
self.fake_api.deployment.check.assert_called_once_with(deployment) self.fake_api.deployment.check.assert_called_once_with(deployment_id)
headers = ["services", "type", "status"] headers = ["services", "type", "status"]
mock_print_list.assert_called_once_with([], headers) mock_print_list.assert_called_once_with([], headers)
def test_deployment_check_not_exist(self):
deployment_id = "e87e4dca-b515-4477-888d-5f6103f13b42"
exc = exceptions.DeploymentNotFound(deployment=deployment_id)
self.fake_api.deployment.get.side_effect = exc
self.assertEqual(self.deployment.check(
self.fake_api, deployment_id), 1)
def test_deployment_check_raise(self): def test_deployment_check_raise(self):
deployment_id = "e87e4dca-b515-4477-888d-5f6103f13b42" deployment_id = "e87e4dca-b515-4477-888d-5f6103f13b42"
sample_credential = fakes.fake_credential( sample_credential = fakes.fake_credential(
auth_url="http://192.168.1.1:5000/v2.0/", auth_url="http://192.168.1.1:5000/v2.0/",
username="admin", password="adminpass") username="admin", password="adminpass")
deployment = self.fake_api.deployment.get.return_value deployment = {"uuid": deployment_id,
deployment.get_credentials_for.return_value = { "credentials": {"openstack": [
"admin": sample_credential, "users": []} {"admin": sample_credential,
"users": [sample_credential]}]}}
self.fake_api.deployment.get.return_value = deployment
refused = keystone_exceptions.ConnectionRefused() refused = keystone_exceptions.ConnectionRefused()
self.fake_api.deployment.check.side_effect = refused self.fake_api.deployment.check.side_effect = refused
self.assertEqual(self.deployment.check( self.assertEqual(self.deployment.check(

View File

@ -15,6 +15,7 @@
"""Tests for db.deploy layer.""" """Tests for db.deploy layer."""
import datetime as dt
import jsonschema import jsonschema
import mock import mock
@ -25,6 +26,8 @@ from tests.unit import test
class DeploymentTestCase(test.TestCase): class DeploymentTestCase(test.TestCase):
TIME_FORMAT = consts.TimeFormat.ISO8601
def setUp(self): def setUp(self):
super(DeploymentTestCase, self).setUp() super(DeploymentTestCase, self).setUp()
self.deployment = { self.deployment = {
@ -229,3 +232,53 @@ class DeploymentTestCase(test.TestCase):
{"completed_at": "fake_time", {"completed_at": "fake_time",
"status": consts.DeployStatus.DEPLOY_FINISHED} "status": consts.DeployStatus.DEPLOY_FINISHED}
) )
def test_to_dict(self):
self.deployment = {
"status": "deploy->finished",
"parent_uuid": None,
"updated_at": dt.datetime(2017, 3, 10, 9, 5, 9, 117427),
"completed_at": dt.datetime(2017, 3, 10, 12, 5, 9, 94981),
"credentials":
{"openstack":
[{"admin":
{"username": "foo_admin_name",
"endpoint": None,
"region_name": "FooRegionOne",
"https_insecure": False,
"permission": "foo_perm",
"tenant_name": "foo_tenant",
"user_domain_name": "Default",
"https_cacert": "",
"domain_name": None,
"endpoint_type": None,
"auth_url": "foo_auth_url",
"password": "admin",
"project_domain_name": "Default"},
"users": []}]},
"started_at": dt.datetime(2017, 3, 10, 12, 5, 9, 78779),
"id": 1,
"name": "foo_deployment_name",
"uuid": "eeecf2c6-8b5d-4ed7-92e5-b7cdc335e885",
"created_at": dt.datetime(2017, 3, 10, 9, 5, 9, 68652),
"config": {
"endpoint": None,
"region_name": "FooRegionOne",
"https_insecure": False,
"admin": {
"username": "foo_admin_name",
"password": "foo_admin_pwd",
"user_domain_name": "Default",
"project_name": "foo_prj_name",
"project_domain_name": "Default"},
"https_cacert": "",
"endpoint_type": None,
"auth_url": "foo_auth_url",
"type": "ExistingCloud"}}
deploy = objects.Deployment(deployment=self.deployment)
expected_result = deploy.to_dict()
for field in ["created_at", "completed_at",
"started_at", "updated_at"]:
self.deployment[field] = self.deployment[field].strftime(
self.TIME_FORMAT)
self.assertEqual(expected_result, self.deployment)

View File

@ -354,7 +354,7 @@ class DeploymentAPITestCase(BaseDeploymentTestCase):
mock_deployment_create.return_value = self.deployment mock_deployment_create.return_value = self.deployment
mock_deployment_update.return_value = self.deployment mock_deployment_update.return_value = self.deployment
dep = api._Deployment.create(self.deployment_config, "fake_deployment") dep = api._Deployment.create(self.deployment_config, "fake_deployment")
self.assertIsInstance(dep, objects.Deployment) self.assertIsInstance(dep, dict)
mock_deployment_create.assert_called_once_with({ mock_deployment_create.assert_called_once_with({
"name": "fake_deployment", "name": "fake_deployment",
"config": self.deployment_config, "config": self.deployment_config,
@ -487,14 +487,16 @@ class DeploymentAPITestCase(BaseDeploymentTestCase):
for key in self.deployment: for key in self.deployment:
self.assertEqual(ret[key], self.deployment[key]) self.assertEqual(ret[key], self.deployment[key])
def test_deployment_check(self): @mock.patch("rally.common.objects.Deployment.get")
def test_deployment_check(self, mock_deployment_get):
fake_credential1 = fakes.fake_credential() fake_credential1 = fakes.fake_credential()
fake_credential2 = fakes.fake_credential() fake_credential2 = fakes.fake_credential()
deployment = mock.Mock(spec=objects.Deployment) mock_deployment_get.return_value.get_credentials_for.return_value = {
deployment.get_credentials_for.return_value = {
"admin": fake_credential1, "users": [fake_credential2]} "admin": fake_credential1, "users": [fake_credential2]}
result = api._Deployment.check(deployment)
result = api._Deployment.check("uuid")
fake_credential1.verify_connection.assert_called_once_with() fake_credential1.verify_connection.assert_called_once_with()
fake_credential2.verify_connection.assert_called_once_with() fake_credential2.verify_connection.assert_called_once_with()
self.assertEqual(fake_credential1.list_services.return_value, result) self.assertEqual(fake_credential1.list_services.return_value, result)