Allow fields filter on single object GETs

The LBaaSv2-API spec had this, and tempest seems to test for it.
We missed adding it when we implemented the v2 API in Pike.

 Conflicts:
	octavia/api/v2/controllers/listener.py

Backport-Candidate: Queens Pike
Change-Id: I16c04b6f12fe4db9f1a2a0dc1d2b6fb54d24fd38
(cherry picked from commit 84ef448a87)
This commit is contained in:
Adam Harwell 2018-04-10 06:04:51 +09:00 committed by Carlos Goncalves
parent 99319c2408
commit dd1f2fe418
16 changed files with 178 additions and 47 deletions

View File

@ -38,8 +38,8 @@ class AmphoraController(base.BaseController):
self.handler = self.handler.amphora self.handler = self.handler.amphora
@wsme_pecan.wsexpose(amp_types.AmphoraRootResponse, wtypes.text, @wsme_pecan.wsexpose(amp_types.AmphoraRootResponse, wtypes.text,
wtypes.text) [wtypes.text], ignore_extra_args=True)
def get_one(self, id): def get_one(self, id, fields=None):
"""Gets a single amphora's details.""" """Gets a single amphora's details."""
context = pecan.request.context.get('octavia_context') context = pecan.request.context.get('octavia_context')
db_amp = self._get_db_amp(context.session, id) db_amp = self._get_db_amp(context.session, id)
@ -49,6 +49,8 @@ class AmphoraController(base.BaseController):
result = self._convert_db_to_type( result = self._convert_db_to_type(
db_amp, amp_types.AmphoraResponse) db_amp, amp_types.AmphoraResponse)
if fields is not None:
result = self._filter_fields([result], fields)[0]
return amp_types.AmphoraRootResponse(amphora=result) return amp_types.AmphoraRootResponse(amphora=result)
@wsme_pecan.wsexpose(amp_types.AmphoraeRootResponse, [wtypes.text], @wsme_pecan.wsexpose(amp_types.AmphoraeRootResponse, [wtypes.text],

View File

@ -54,8 +54,8 @@ class HealthMonitorController(base.BaseController):
return db_hm return db_hm
@wsme_pecan.wsexpose(hm_types.HealthMonitorRootResponse, wtypes.text, @wsme_pecan.wsexpose(hm_types.HealthMonitorRootResponse, wtypes.text,
wtypes.text) [wtypes.text], ignore_extra_args=True)
def get_one(self, id): def get_one(self, id, fields=None):
"""Gets a single healthmonitor's details.""" """Gets a single healthmonitor's details."""
context = pecan.request.context.get('octavia_context') context = pecan.request.context.get('octavia_context')
db_hm = self._get_db_hm(context.session, id) db_hm = self._get_db_hm(context.session, id)
@ -65,6 +65,8 @@ class HealthMonitorController(base.BaseController):
result = self._convert_db_to_type( result = self._convert_db_to_type(
db_hm, hm_types.HealthMonitorResponse) db_hm, hm_types.HealthMonitorResponse)
if fields is not None:
result = self._filter_fields([result], fields)[0]
return hm_types.HealthMonitorRootResponse(healthmonitor=result) return hm_types.HealthMonitorRootResponse(healthmonitor=result)
@wsme_pecan.wsexpose(hm_types.HealthMonitorsRootResponse, wtypes.text, @wsme_pecan.wsexpose(hm_types.HealthMonitorsRootResponse, wtypes.text,

View File

@ -43,8 +43,9 @@ class L7PolicyController(base.BaseController):
super(L7PolicyController, self).__init__() super(L7PolicyController, self).__init__()
self.handler = self.handler.l7policy self.handler = self.handler.l7policy
@wsme_pecan.wsexpose(l7policy_types.L7PolicyRootResponse, wtypes.text) @wsme_pecan.wsexpose(l7policy_types.L7PolicyRootResponse, wtypes.text,
def get(self, id): [wtypes.text], ignore_extra_args=True)
def get(self, id, fields=None):
"""Gets a single l7policy's details.""" """Gets a single l7policy's details."""
context = pecan.request.context.get('octavia_context') context = pecan.request.context.get('octavia_context')
db_l7policy = self._get_db_l7policy(context.session, id) db_l7policy = self._get_db_l7policy(context.session, id)
@ -52,8 +53,10 @@ class L7PolicyController(base.BaseController):
self._auth_validate_action(context, db_l7policy.project_id, self._auth_validate_action(context, db_l7policy.project_id,
constants.RBAC_GET_ONE) constants.RBAC_GET_ONE)
result = self._convert_db_to_type(db_l7policy, result = self._convert_db_to_type(
l7policy_types.L7PolicyResponse) db_l7policy, l7policy_types.L7PolicyResponse)
if fields is not None:
result = self._filter_fields([result], fields)[0]
return l7policy_types.L7PolicyRootResponse(l7policy=result) return l7policy_types.L7PolicyRootResponse(l7policy=result)
@wsme_pecan.wsexpose(l7policy_types.L7PoliciesRootResponse, wtypes.text, @wsme_pecan.wsexpose(l7policy_types.L7PoliciesRootResponse, wtypes.text,

View File

@ -41,8 +41,9 @@ class L7RuleController(base.BaseController):
self.l7policy_id = l7policy_id self.l7policy_id = l7policy_id
self.handler = self.handler.l7rule self.handler = self.handler.l7rule
@wsme_pecan.wsexpose(l7rule_types.L7RuleRootResponse, wtypes.text) @wsme_pecan.wsexpose(l7rule_types.L7RuleRootResponse, wtypes.text,
def get(self, id): [wtypes.text], ignore_extra_args=True)
def get(self, id, fields=None):
"""Gets a single l7rule's details.""" """Gets a single l7rule's details."""
context = pecan.request.context.get('octavia_context') context = pecan.request.context.get('octavia_context')
db_l7rule = self._get_db_l7rule(context.session, id) db_l7rule = self._get_db_l7rule(context.session, id)
@ -50,8 +51,10 @@ class L7RuleController(base.BaseController):
self._auth_validate_action(context, db_l7rule.project_id, self._auth_validate_action(context, db_l7rule.project_id,
constants.RBAC_GET_ONE) constants.RBAC_GET_ONE)
result = self._convert_db_to_type(db_l7rule, result = self._convert_db_to_type(
l7rule_types.L7RuleResponse) db_l7rule, l7rule_types.L7RuleResponse)
if fields is not None:
result = self._filter_fields([result], fields)[0]
return l7rule_types.L7RuleRootResponse(rule=result) return l7rule_types.L7RuleRootResponse(rule=result)
@wsme_pecan.wsexpose(l7rule_types.L7RulesRootResponse, [wtypes.text], @wsme_pecan.wsexpose(l7rule_types.L7RulesRootResponse, [wtypes.text],

View File

@ -63,8 +63,9 @@ class ListenersController(base.BaseController):
resource=data_models.Listener._name(), id=id) resource=data_models.Listener._name(), id=id)
return db_listener return db_listener
@wsme_pecan.wsexpose(listener_types.ListenerRootResponse, wtypes.text) @wsme_pecan.wsexpose(listener_types.ListenerRootResponse, wtypes.text,
def get_one(self, id): [wtypes.text], ignore_extra_args=True)
def get_one(self, id, fields=None):
"""Gets a single listener's details.""" """Gets a single listener's details."""
context = pecan.request.context.get('octavia_context') context = pecan.request.context.get('octavia_context')
db_listener = self._get_db_listener(context.session, id) db_listener = self._get_db_listener(context.session, id)
@ -74,6 +75,8 @@ class ListenersController(base.BaseController):
result = self._convert_db_to_type(db_listener, result = self._convert_db_to_type(db_listener,
listener_types.ListenerResponse) listener_types.ListenerResponse)
if fields is not None:
result = self._filter_fields([result], fields)[0]
return listener_types.ListenerRootResponse(listener=result) return listener_types.ListenerRootResponse(listener=result)
@wsme_pecan.wsexpose(listener_types.ListenersRootResponse, wtypes.text, @wsme_pecan.wsexpose(listener_types.ListenersRootResponse, wtypes.text,

View File

@ -49,8 +49,9 @@ class LoadBalancersController(base.BaseController):
super(LoadBalancersController, self).__init__() super(LoadBalancersController, self).__init__()
self.handler = self.handler.load_balancer self.handler = self.handler.load_balancer
@wsme_pecan.wsexpose(lb_types.LoadBalancerRootResponse, wtypes.text) @wsme_pecan.wsexpose(lb_types.LoadBalancerRootResponse, wtypes.text,
def get_one(self, id): [wtypes.text], ignore_extra_args=True)
def get_one(self, id, fields=None):
"""Gets a single load balancer's details.""" """Gets a single load balancer's details."""
context = pecan.request.context.get('octavia_context') context = pecan.request.context.get('octavia_context')
load_balancer = self._get_db_lb(context.session, id) load_balancer = self._get_db_lb(context.session, id)
@ -60,6 +61,8 @@ class LoadBalancersController(base.BaseController):
result = self._convert_db_to_type( result = self._convert_db_to_type(
load_balancer, lb_types.LoadBalancerResponse) load_balancer, lb_types.LoadBalancerResponse)
if fields is not None:
result = self._filter_fields([result], fields)[0]
return lb_types.LoadBalancerRootResponse(loadbalancer=result) return lb_types.LoadBalancerRootResponse(loadbalancer=result)
@wsme_pecan.wsexpose(lb_types.LoadBalancersRootResponse, wtypes.text, @wsme_pecan.wsexpose(lb_types.LoadBalancersRootResponse, wtypes.text,

View File

@ -42,8 +42,9 @@ class MemberController(base.BaseController):
self.pool_id = pool_id self.pool_id = pool_id
self.handler = self.handler.member self.handler = self.handler.member
@wsme_pecan.wsexpose(member_types.MemberRootResponse, wtypes.text) @wsme_pecan.wsexpose(member_types.MemberRootResponse, wtypes.text,
def get(self, id): [wtypes.text], ignore_extra_args=True)
def get(self, id, fields=None):
"""Gets a single pool member's details.""" """Gets a single pool member's details."""
context = pecan.request.context.get('octavia_context') context = pecan.request.context.get('octavia_context')
db_member = self._get_db_member(context.session, id) db_member = self._get_db_member(context.session, id)
@ -51,8 +52,10 @@ class MemberController(base.BaseController):
self._auth_validate_action(context, db_member.project_id, self._auth_validate_action(context, db_member.project_id,
constants.RBAC_GET_ONE) constants.RBAC_GET_ONE)
result = self._convert_db_to_type(db_member, result = self._convert_db_to_type(
member_types.MemberResponse) db_member, member_types.MemberResponse)
if fields is not None:
result = self._filter_fields([result], fields)[0]
return member_types.MemberRootResponse(member=result) return member_types.MemberRootResponse(member=result)
@wsme_pecan.wsexpose(member_types.MembersRootResponse, [wtypes.text], @wsme_pecan.wsexpose(member_types.MembersRootResponse, [wtypes.text],

View File

@ -45,8 +45,9 @@ class PoolsController(base.BaseController):
super(PoolsController, self).__init__() super(PoolsController, self).__init__()
self.handler = self.handler.pool self.handler = self.handler.pool
@wsme_pecan.wsexpose(pool_types.PoolRootResponse, wtypes.text) @wsme_pecan.wsexpose(pool_types.PoolRootResponse, wtypes.text,
def get(self, id): [wtypes.text], ignore_extra_args=True)
def get(self, id, fields=None):
"""Gets a pool's details.""" """Gets a pool's details."""
context = pecan.request.context.get('octavia_context') context = pecan.request.context.get('octavia_context')
db_pool = self._get_db_pool(context.session, id) db_pool = self._get_db_pool(context.session, id)
@ -55,6 +56,8 @@ class PoolsController(base.BaseController):
constants.RBAC_GET_ONE) constants.RBAC_GET_ONE)
result = self._convert_db_to_type(db_pool, pool_types.PoolResponse) result = self._convert_db_to_type(db_pool, pool_types.PoolResponse)
if fields is not None:
result = self._filter_fields([result], fields)[0]
return pool_types.PoolRootResponse(pool=result) return pool_types.PoolRootResponse(pool=result)
@wsme_pecan.wsexpose(pool_types.PoolsRootResponse, wtypes.text, @wsme_pecan.wsexpose(pool_types.PoolsRootResponse, wtypes.text,

View File

@ -285,9 +285,17 @@ class TestAmphora(base.BaseAPITest):
amps = self.get(self.AMPHORAE_PATH, params={ amps = self.get(self.AMPHORAE_PATH, params={
'fields': ['id', 'role']}).json 'fields': ['id', 'role']}).json
for amp in amps['amphorae']: for amp in amps['amphorae']:
self.assertIn(u'id', amp.keys()) self.assertIn(u'id', amp)
self.assertIn(u'role', amp.keys()) self.assertIn(u'role', amp)
self.assertNotIn(u'ha_port_id', amp.keys()) self.assertNotIn(u'ha_port_id', amp)
def test_get_one_fields_filter(self):
amp = self.get(
self.AMPHORA_PATH.format(amphora_id=self.amp_id),
params={'fields': ['id', 'role']}).json.get(self.root_tag)
self.assertIn(u'id', amp)
self.assertIn(u'role', amp)
self.assertNotIn(u'ha_port_id', amp)
def test_get_all_filter(self): def test_get_all_filter(self):
self._create_additional_amp() self._create_additional_amp()

View File

@ -512,9 +512,30 @@ class TestHealthMonitor(base.BaseAPITest):
hms = self.get(self.HMS_PATH, params={ hms = self.get(self.HMS_PATH, params={
'fields': ['id', 'project_id']}).json 'fields': ['id', 'project_id']}).json
for hm in hms['healthmonitors']: for hm in hms['healthmonitors']:
self.assertIn(u'id', hm.keys()) self.assertIn(u'id', hm)
self.assertIn(u'project_id', hm.keys()) self.assertIn(u'project_id', hm)
self.assertNotIn(u'description', hm.keys()) self.assertNotIn(u'description', hm)
def test_get_one_fields_filter(self):
pool1 = self.create_pool(
self.lb_id,
constants.PROTOCOL_HTTP,
constants.LB_ALGORITHM_ROUND_ROBIN,
name='pool1').get('pool')
self.set_lb_status(self.lb_id)
self.set_lb_status(self.lb_id)
hm1 = self.create_health_monitor(
pool1.get('id'), constants.HEALTH_MONITOR_HTTP,
1, 1, 1, 1, name='hm1').get(self.root_tag)
self.set_lb_status(self.lb_id)
hm = self.get(
self.HM_PATH.format(healthmonitor_id=hm1.get('id')),
params={'fields': ['id', 'project_id']}).json.get(self.root_tag)
self.assertIn(u'id', hm)
self.assertIn(u'project_id', hm)
self.assertNotIn(u'description', hm)
def test_get_all_filter(self): def test_get_all_filter(self):
pool1 = self.create_pool( pool1 = self.create_pool(

View File

@ -448,9 +448,22 @@ class TestL7Policy(base.BaseAPITest):
l7pos = self.get(self.L7POLICIES_PATH, params={ l7pos = self.get(self.L7POLICIES_PATH, params={
'fields': ['id', 'project_id']}).json 'fields': ['id', 'project_id']}).json
for l7po in l7pos['l7policies']: for l7po in l7pos['l7policies']:
self.assertIn(u'id', l7po.keys()) self.assertIn(u'id', l7po)
self.assertIn(u'project_id', l7po.keys()) self.assertIn(u'project_id', l7po)
self.assertNotIn(u'description', l7po.keys()) self.assertNotIn(u'description', l7po)
def test_get_one_fields_filter(self):
l7p1 = self.create_l7policy(
self.listener_id, constants.L7POLICY_ACTION_REJECT,
name='policy1').get(self.root_tag)
self.set_lb_status(self.lb_id)
l7po = self.get(
self.L7POLICY_PATH.format(l7policy_id=l7p1.get('id')),
params={'fields': ['id', 'project_id']}).json.get(self.root_tag)
self.assertIn(u'id', l7po)
self.assertIn(u'project_id', l7po)
self.assertNotIn(u'description', l7po)
def test_get_all_filter(self): def test_get_all_filter(self):
policy1 = self.create_l7policy( policy1 = self.create_l7policy(

View File

@ -311,9 +311,23 @@ class TestL7Rule(base.BaseAPITest):
l7rus = self.get(self.l7rules_path, params={ l7rus = self.get(self.l7rules_path, params={
'fields': ['id', 'compare_type']}).json 'fields': ['id', 'compare_type']}).json
for l7ru in l7rus['rules']: for l7ru in l7rus['rules']:
self.assertIn(u'id', l7ru.keys()) self.assertIn(u'id', l7ru)
self.assertIn(u'compare_type', l7ru.keys()) self.assertIn(u'compare_type', l7ru)
self.assertNotIn(u'project_id', l7ru.keys()) self.assertNotIn(u'project_id', l7ru)
def test_get_one_fields_filter(self):
l7r1 = self.create_l7rule(
self.l7policy_id, constants.L7RULE_TYPE_PATH,
constants.L7RULE_COMPARE_TYPE_STARTS_WITH,
'/api').get(self.root_tag)
self.set_lb_status(self.lb_id)
l7ru = self.get(
self.l7rule_path.format(l7rule_id=l7r1.get('id')),
params={'fields': ['id', 'compare_type']}).json.get(self.root_tag)
self.assertIn(u'id', l7ru)
self.assertIn(u'compare_type', l7ru)
self.assertNotIn(u'project_id', l7ru)
def test_get_all_filter(self): def test_get_all_filter(self):
ru1 = self.create_l7rule( ru1 = self.create_l7rule(

View File

@ -324,9 +324,22 @@ class TestListener(base.BaseAPITest):
lis = self.get(self.LISTENERS_PATH, params={ lis = self.get(self.LISTENERS_PATH, params={
'fields': ['id', 'project_id']}).json 'fields': ['id', 'project_id']}).json
for li in lis['listeners']: for li in lis['listeners']:
self.assertIn(u'id', li.keys()) self.assertIn(u'id', li)
self.assertIn(u'project_id', li.keys()) self.assertIn(u'project_id', li)
self.assertNotIn(u'description', li.keys()) self.assertNotIn(u'description', li)
def test_get_one_fields_filter(self):
listener1 = self.create_listener(
constants.PROTOCOL_HTTP, 80, self.lb_id,
name='listener1').get(self.root_tag)
self.set_lb_status(self.lb_id)
li = self.get(
self.LISTENER_PATH.format(listener_id=listener1.get('id')),
params={'fields': ['id', 'project_id']}).json.get(self.root_tag)
self.assertIn(u'id', li)
self.assertIn(u'project_id', li)
self.assertNotIn(u'description', li)
def test_get_all_filter(self): def test_get_all_filter(self):
li1 = self.create_listener(constants.PROTOCOL_HTTP, li1 = self.create_listener(constants.PROTOCOL_HTTP,

View File

@ -1034,9 +1034,21 @@ class TestLoadBalancer(base.BaseAPITest):
lbs = self.get(self.LBS_PATH, params={ lbs = self.get(self.LBS_PATH, params={
'fields': ['id', 'project_id']}).json 'fields': ['id', 'project_id']}).json
for lb in lbs['loadbalancers']: for lb in lbs['loadbalancers']:
self.assertIn(u'id', lb.keys()) self.assertIn(u'id', lb)
self.assertIn(u'project_id', lb.keys()) self.assertIn(u'project_id', lb)
self.assertNotIn(u'description', lb.keys()) self.assertNotIn(u'description', lb)
def test_get_one_fields_filter(self):
lb1 = self.create_load_balancer(
uuidutils.generate_uuid(),
name='lb1', project_id=self.project_id).get(self.root_tag)
lb = self.get(
self.LB_PATH.format(lb_id=lb1.get('id')),
params={'fields': ['id', 'project_id']}).json.get(self.root_tag)
self.assertIn(u'id', lb)
self.assertIn(u'project_id', lb)
self.assertNotIn(u'description', lb)
def test_get_all_admin_state_up_filter(self): def test_get_all_admin_state_up_filter(self):
self.create_load_balancer(uuidutils.generate_uuid(), self.create_load_balancer(uuidutils.generate_uuid(),

View File

@ -289,10 +289,23 @@ class TestMember(base.BaseAPITest):
members = self.get(self.members_path, params={ members = self.get(self.members_path, params={
'fields': ['id', 'address']}).json 'fields': ['id', 'address']}).json
for member in members['members']: for member in members['members']:
self.assertIn(u'id', member.keys()) self.assertIn(u'id', member)
self.assertIn(u'address', member.keys()) self.assertIn(u'address', member)
self.assertNotIn(u'name', member.keys()) self.assertNotIn(u'name', member)
self.assertNotIn(u'monitor_address', member.keys()) self.assertNotIn(u'monitor_address', member)
def test_get_one_fields_filter(self):
member1 = self.create_member(
self.pool_id, '192.0.2.1', 80, name='member1').get(self.root_tag)
self.set_lb_status(self.lb_id)
member = self.get(
self.member_path.format(member_id=member1.get('id')),
params={'fields': ['id', 'address']}).json.get(self.root_tag)
self.assertIn(u'id', member)
self.assertIn(u'address', member)
self.assertNotIn(u'name', member)
self.assertNotIn(u'monitor_address', member)
def test_get_all_filter(self): def test_get_all_filter(self):
mem1 = self.create_member(self.pool_id, mem1 = self.create_member(self.pool_id,

View File

@ -472,9 +472,24 @@ class TestPool(base.BaseAPITest):
pools = self.get(self.POOLS_PATH, params={ pools = self.get(self.POOLS_PATH, params={
'fields': ['id', 'project_id']}).json 'fields': ['id', 'project_id']}).json
for pool in pools['pools']: for pool in pools['pools']:
self.assertIn(u'id', pool.keys()) self.assertIn(u'id', pool)
self.assertIn(u'project_id', pool.keys()) self.assertIn(u'project_id', pool)
self.assertNotIn(u'description', pool.keys()) self.assertNotIn(u'description', pool)
def test_get_one_fields_filter(self):
pool1 = self.create_pool(
self.lb_id,
constants.PROTOCOL_HTTP,
constants.LB_ALGORITHM_ROUND_ROBIN,
name='pool1').get(self.root_tag)
self.set_lb_status(lb_id=self.lb_id)
pool = self.get(
self.POOL_PATH.format(pool_id=pool1.get('id')),
params={'fields': ['id', 'project_id']}).json.get(self.root_tag)
self.assertIn(u'id', pool)
self.assertIn(u'project_id', pool)
self.assertNotIn(u'description', pool)
def test_get_all_filter(self): def test_get_all_filter(self):
po1 = self.create_pool( po1 = self.create_pool(