Fix missing fields in API response

Previously, if some fields are not set during object creation in
database, they are not shown in API response, which will cause some
issues for python-qinlingclient. For those missing fields, qinling
client will make an extra API request which is not efficient.

Change-Id: If6d95b6fe11b56183cf05291daaed233ad347cb0
This commit is contained in:
Lingxian Kong 2018-04-30 12:25:33 +12:00
parent 68b261d83d
commit 0e8d91c30b
7 changed files with 23 additions and 27 deletions

View File

@ -64,7 +64,7 @@ class ExecutionsController(rest.RestController):
db_model = executions.create_execution(self.engine_client, params) db_model = executions.create_execution(self.engine_client, params)
return resources.Execution.from_dict(db_model.to_dict()) return resources.Execution.from_db_obj(db_model)
@rest_utils.wrap_wsme_controller_exception @rest_utils.wrap_wsme_controller_exception
@wsme_pecan.wsexpose(resources.Executions, wtypes.text, bool, wtypes.text, @wsme_pecan.wsexpose(resources.Executions, wtypes.text, bool, wtypes.text,
@ -95,7 +95,7 @@ class ExecutionsController(rest.RestController):
LOG.info("Get all %ss. filters=%s", self.type, filters) LOG.info("Get all %ss. filters=%s", self.type, filters)
db_execs = db_api.get_executions(insecure=all_projects, **filters) db_execs = db_api.get_executions(insecure=all_projects, **filters)
executions = [resources.Execution.from_dict(db_model.to_dict()) executions = [resources.Execution.from_db_obj(db_model)
for db_model in db_execs] for db_model in db_execs]
return resources.Executions(executions=executions) return resources.Executions(executions=executions)
@ -107,7 +107,7 @@ class ExecutionsController(rest.RestController):
execution_db = db_api.get_execution(id) execution_db = db_api.get_execution(id)
return resources.Execution.from_dict(execution_db.to_dict()) return resources.Execution.from_db_obj(execution_db)
@rest_utils.wrap_wsme_controller_exception @rest_utils.wrap_wsme_controller_exception
@wsme_pecan.wsexpose(None, types.uuid, status_code=204) @wsme_pecan.wsexpose(None, types.uuid, status_code=204)

View File

@ -111,7 +111,7 @@ class FunctionsController(rest.RestController):
if not download: if not download:
pecan.override_template('json') pecan.override_template('json')
return resources.Function.from_dict(func_db.to_dict()).to_dict() return resources.Function.from_db_obj(func_db).to_dict()
else: else:
LOG.info("Downloading function %s", id) LOG.info("Downloading function %s", id)
source = func_db.code['source'] source = func_db.code['source']
@ -230,7 +230,7 @@ class FunctionsController(rest.RestController):
raise e raise e
pecan.response.status = 201 pecan.response.status = 201
return resources.Function.from_dict(func_db.to_dict()).to_dict() return resources.Function.from_db_obj(func_db).to_dict()
@rest_utils.wrap_wsme_controller_exception @rest_utils.wrap_wsme_controller_exception
@wsme_pecan.wsexpose(resources.Functions, bool, wtypes.text) @wsme_pecan.wsexpose(resources.Functions, bool, wtypes.text)
@ -252,7 +252,7 @@ class FunctionsController(rest.RestController):
) )
LOG.info("Get all functions. filters=%s", filters) LOG.info("Get all functions. filters=%s", filters)
db_functions = db_api.get_functions(insecure=all_projects, **filters) db_functions = db_api.get_functions(insecure=all_projects, **filters)
functions = [resources.Function.from_dict(db_model.to_dict()) functions = [resources.Function.from_db_obj(db_model)
for db_model in db_functions] for db_model in db_functions]
return resources.Functions(functions=functions) return resources.Functions(functions=functions)
@ -422,7 +422,7 @@ class FunctionsController(rest.RestController):
self.storage_provider.delete(ctx.projectid, id, pre_md5sum) self.storage_provider.delete(ctx.projectid, id, pre_md5sum)
pecan.response.status = 200 pecan.response.status = 200
return resources.Function.from_dict(func_db.to_dict()).to_dict() return resources.Function.from_db_obj(func_db).to_dict()
@rest_utils.wrap_wsme_controller_exception @rest_utils.wrap_wsme_controller_exception
@wsme_pecan.wsexpose( @wsme_pecan.wsexpose(

View File

@ -135,7 +135,7 @@ class FunctionVersionsController(rest.RestController):
version = self._create_function_version(ctx.project_id, function_id, version = self._create_function_version(ctx.project_id, function_id,
**values) **values)
return resources.FunctionVersion.from_dict(version.to_dict()) return resources.FunctionVersion.from_db_obj(version)
@rest_utils.wrap_wsme_controller_exception @rest_utils.wrap_wsme_controller_exception
@wsme_pecan.wsexpose(resources.FunctionVersions, types.uuid) @wsme_pecan.wsexpose(resources.FunctionVersions, types.uuid)
@ -148,7 +148,7 @@ class FunctionVersionsController(rest.RestController):
func_db = db_api.get_function(function_id) func_db = db_api.get_function(function_id)
db_versions = func_db.versions db_versions = func_db.versions
versions = [resources.FunctionVersion.from_dict(v.to_dict()) versions = [resources.FunctionVersion.from_db_obj(v)
for v in db_versions] for v in db_versions]
return resources.FunctionVersions(function_versions=versions) return resources.FunctionVersions(function_versions=versions)
@ -170,8 +170,7 @@ class FunctionVersionsController(rest.RestController):
LOG.info("Getting version %s for function %s.", version, LOG.info("Getting version %s for function %s.", version,
function_id) function_id)
pecan.override_template('json') pecan.override_template('json')
return resources.FunctionVersion.from_dict( return resources.FunctionVersion.from_db_obj(version_db).to_dict()
version_db.to_dict()).to_dict()
LOG.info("Downloading version %s for function %s.", version, LOG.info("Downloading version %s for function %s.", version,
function_id) function_id)

View File

@ -81,7 +81,7 @@ class JobsController(rest.RestController):
} }
db_job = db_api.create_job(values) db_job = db_api.create_job(values)
return resources.Job.from_dict(db_job.to_dict()) return resources.Job.from_db_obj(db_job)
@rest_utils.wrap_wsme_controller_exception @rest_utils.wrap_wsme_controller_exception
@wsme_pecan.wsexpose(None, types.uuid, status_code=204) @wsme_pecan.wsexpose(None, types.uuid, status_code=204)
@ -95,7 +95,7 @@ class JobsController(rest.RestController):
LOG.info("Get resource.", resource={'type': self.type, 'id': id}) LOG.info("Get resource.", resource={'type': self.type, 'id': id})
job_db = db_api.get_job(id) job_db = db_api.get_job(id)
return resources.Job.from_dict(job_db.to_dict()) return resources.Job.from_db_obj(job_db)
@rest_utils.wrap_wsme_controller_exception @rest_utils.wrap_wsme_controller_exception
@wsme_pecan.wsexpose(resources.Jobs, bool, wtypes.text) @wsme_pecan.wsexpose(resources.Jobs, bool, wtypes.text)
@ -111,7 +111,7 @@ class JobsController(rest.RestController):
) )
LOG.info("Get all %ss. filters=%s", self.type, filters) LOG.info("Get all %ss. filters=%s", self.type, filters)
db_jobs = db_api.get_jobs(insecure=all_projects, **filters) db_jobs = db_api.get_jobs(insecure=all_projects, **filters)
jobs = [resources.Job.from_dict(db_model.to_dict()) jobs = [resources.Job.from_db_obj(db_model)
for db_model in db_jobs] for db_model in db_jobs]
return resources.Jobs(jobs=jobs) return resources.Jobs(jobs=jobs)
@ -177,4 +177,4 @@ class JobsController(rest.RestController):
).get_next(datetime.datetime) ).get_next(datetime.datetime)
updated_job = db_api.update_job(id, values) updated_job = db_api.update_job(id, values)
return resources.Job.from_dict(updated_job.to_dict()) return resources.Job.from_db_obj(updated_job)

View File

@ -45,6 +45,10 @@ class Resource(wtypes.Base):
return obj return obj
@classmethod
def from_db_obj(cls, db_obj):
return cls.from_dict(db_obj.to_dict())
def __str__(self): def __str__(self):
"""WSME based implementation of __str__.""" """WSME based implementation of __str__."""

View File

@ -47,14 +47,14 @@ class RuntimesController(rest.RestController):
runtime_db = db_api.get_runtime(id) runtime_db = db_api.get_runtime(id)
return resources.Runtime.from_dict(runtime_db.to_dict()) return resources.Runtime.from_db_obj(runtime_db)
@rest_utils.wrap_wsme_controller_exception @rest_utils.wrap_wsme_controller_exception
@wsme_pecan.wsexpose(resources.Runtimes) @wsme_pecan.wsexpose(resources.Runtimes)
def get_all(self): def get_all(self):
LOG.info("Get all %ss.", self.type) LOG.info("Get all %ss.", self.type)
runtimes = [resources.Runtime.from_dict(db_model.to_dict()) runtimes = [resources.Runtime.from_db_obj(db_model)
for db_model in db_api.get_runtimes()] for db_model in db_api.get_runtimes()]
return resources.Runtimes(runtimes=runtimes) return resources.Runtimes(runtimes=runtimes)
@ -82,7 +82,7 @@ class RuntimesController(rest.RestController):
db_model = db_api.create_runtime(params) db_model = db_api.create_runtime(params)
self.engine_client.create_runtime(db_model.id) self.engine_client.create_runtime(db_model.id)
return resources.Runtime.from_dict(db_model.to_dict()) return resources.Runtime.from_db_obj(db_model)
@rest_utils.wrap_wsme_controller_exception @rest_utils.wrap_wsme_controller_exception
@wsme_pecan.wsexpose(None, types.uuid, status_code=204) @wsme_pecan.wsexpose(None, types.uuid, status_code=204)
@ -161,4 +161,4 @@ class RuntimesController(rest.RestController):
runtime_db = db_api.update_runtime(id, values) runtime_db = db_api.update_runtime(id, values)
return resources.Runtime.from_dict(runtime_db.to_dict()) return resources.Runtime.from_db_obj(runtime_db)

View File

@ -15,7 +15,6 @@
from oslo_db.sqlalchemy import models as oslo_models from oslo_db.sqlalchemy import models as oslo_models
import sqlalchemy as sa import sqlalchemy as sa
from sqlalchemy.ext import declarative from sqlalchemy.ext import declarative
from sqlalchemy.orm import attributes
from qinling import context from qinling import context
from qinling.utils import common from qinling.utils import common
@ -65,14 +64,8 @@ class _QinlingModelBase(oslo_models.ModelBase, oslo_models.TimestampMixin):
"""sqlalchemy based automatic to_dict method.""" """sqlalchemy based automatic to_dict method."""
d = {} d = {}
# If a column is unloaded at this point, it is
# probably deferred. We do not want to access it
# here and thereby cause it to load.
unloaded = attributes.instance_state(self).unloaded
for col in self.__table__.columns: for col in self.__table__.columns:
if col.name not in unloaded and hasattr(self, col.name): d[col.name] = getattr(self, col.name)
d[col.name] = getattr(self, col.name)
common.datetime_to_str(d, 'created_at') common.datetime_to_str(d, 'created_at')
common.datetime_to_str(d, 'updated_at') common.datetime_to_str(d, 'updated_at')