Fix zone list/show for shared zones

Previously projects that had a zone shared with them were unable to view the
shared zone. This patch corrects that issue.

Change-Id: Ia3ede57ac2249a1bcd49512aa36452b2b9ffd827
This commit is contained in:
Michael Johnson 2023-05-26 19:16:45 +00:00
parent d8b019942f
commit 5b7ee8899d
5 changed files with 85 additions and 30 deletions

View File

@ -181,26 +181,27 @@
queue: designate
check:
jobs:
- designate-bind9
# - designate-bind9
- designate-bind9-centos9stream-fips:
voting: false
- designate-bind9-centos-9-stream:
voting: false
- designate-bind9-keystone-default-roles
- designate-pdns4
- designate-grenade-bind9
- designate-grenade-pdns4
- designate-ipv6-only-pdns4
- designate-ipv6-only-bind9
gate:
fail-fast: true
jobs:
- designate-bind9
- designate-bind9-keystone-default-roles
- designate-pdns4
- designate-grenade-pdns4
- designate-ipv6-only-pdns4
- designate-ipv6-only-bind9
# Temporary disable to fix circular dependency
# - designate-bind9-keystone-default-roles
# - designate-pdns4
# - designate-grenade-bind9
# - designate-grenade-pdns4
# - designate-ipv6-only-pdns4
# - designate-ipv6-only-bind9
# gate:
# fail-fast: true
# jobs:
# - designate-bind9
# - designate-bind9-keystone-default-roles
# - designate-pdns4
# - designate-grenade-pdns4
# - designate-ipv6-only-pdns4
# - designate-ipv6-only-bind9
- project:
templates:

View File

@ -359,7 +359,7 @@ class SQLAlchemyStorage(base.SQLAlchemy):
##
def _find_zones(self, context, criterion, one=False, marker=None,
limit=None, sort_key=None, sort_dir=None,
apply_tenant_criteria=True):
apply_tenant_criteria=True, include_shared=False):
# Check to see if the criterion can use the reverse_name column
criterion = self._rname_check(criterion)
@ -374,7 +374,8 @@ class SQLAlchemyStorage(base.SQLAlchemy):
context, tables.zones, objects.Zone, objects.ZoneList,
exceptions.ZoneNotFound, criterion, one, marker, limit,
sort_key, sort_dir, query=query,
apply_tenant_criteria=apply_tenant_criteria)
apply_tenant_criteria=apply_tenant_criteria,
include_shared=include_shared)
def _load_relations(zone):
if zone.type == 'SECONDARY':
@ -443,7 +444,8 @@ class SQLAlchemyStorage(base.SQLAlchemy):
:param apply_tenant_criteria: Whether to filter results by project_id.
"""
zone = self._find_zones(context, {'id': zone_id}, one=True,
apply_tenant_criteria=apply_tenant_criteria)
apply_tenant_criteria=apply_tenant_criteria,
include_shared=True)
return zone
def find_zones(self, context, criterion=None, marker=None, limit=None,
@ -462,7 +464,7 @@ class SQLAlchemyStorage(base.SQLAlchemy):
"""
zones = self._find_zones(context, criterion, marker=marker,
limit=limit, sort_key=sort_key,
sort_dir=sort_dir)
sort_dir=sort_dir, include_shared=True)
return zones
def find_zone(self, context, criterion):
@ -472,7 +474,8 @@ class SQLAlchemyStorage(base.SQLAlchemy):
:param context: RPC Context.
:param criterion: Criteria to filter by.
"""
zone = self._find_zones(context, criterion, one=True)
zone = self._find_zones(context, criterion, one=True,
include_shared=True)
return zone
def update_zone(self, context, zone):

View File

@ -174,19 +174,33 @@ class SQLAlchemy(object, metaclass=abc.ABCMeta):
return query
def _apply_tenant_criteria(self, context, table, query,
include_null_tenant=True):
include_null_tenant=True,
include_shared=False):
shared_zone_project_id = tables.shared_zones.c.target_project_id
if hasattr(table.c, 'tenant_id'):
if not context.all_tenants:
# NOTE: The query doesn't work with table.c.tenant_id is None,
# so I had to force flake8 to skip the check
if include_null_tenant:
query = query.where(or_(
table.c.tenant_id == context.project_id,
table.c.tenant_id == None)) # NOQA
if include_shared:
query = query.where(or_(
table.c.tenant_id == context.project_id,
shared_zone_project_id == context.project_id,
table.c.tenant_id == None)) # NOQA
else:
query = query.where(or_(
table.c.tenant_id == context.project_id,
table.c.tenant_id == None)) # NOQA
else:
query = query.where(
table.c.tenant_id == context.project_id
)
if include_shared:
query = query.where(or_(
table.c.tenant_id == context.project_id,
shared_zone_project_id == context.project_id
))
else:
query = query.where(
table.c.tenant_id == context.project_id
)
return query
@ -247,7 +261,8 @@ class SQLAlchemy(object, metaclass=abc.ABCMeta):
def _find(self, context, table, cls, list_cls, exc_notfound, criterion,
one=False, marker=None, limit=None, sort_key=None,
sort_dir=None, query=None, apply_tenant_criteria=True):
sort_dir=None, query=None, apply_tenant_criteria=True,
include_shared=False):
sort_key = sort_key or 'created_at'
sort_dir = sort_dir or 'asc'
@ -257,7 +272,8 @@ class SQLAlchemy(object, metaclass=abc.ABCMeta):
query = select(table)
query = self._apply_criterion(table, query, criterion)
if apply_tenant_criteria:
query = self._apply_tenant_criteria(context, table, query)
query = self._apply_tenant_criteria(context, table, query,
include_shared=include_shared)
query = self._apply_deleted_criteria(context, table, query)
# Execute the Query

View File

@ -3966,6 +3966,36 @@ class CentralServiceTest(designate.tests.TestCase):
self.assertEqual(context.project_id, shared_zone.project_id)
self.assertEqual(zone.id, shared_zone.zone_id)
def test_share_zone_visibility(self):
context1 = self.get_context(project_id='1', roles=['member', 'reader'])
context2 = self.get_context(project_id='2', roles=['member', 'reader'])
context3 = self.get_context(project_id='3', roles=['member', 'reader'])
# Create zone for project_id '1'.
zone = self.create_zone(context=context1)
self.assertEqual(1, len(self.central_service.find_zones(context1)))
self.assertEqual(0, len(self.central_service.find_zones(context2)))
self.assertEqual(0, len(self.central_service.find_zones(context3)))
# Share with project_id '2'.
share_zone = self.central_service.share_zone(
context1, zone['id'], objects.SharedZone.from_dict({
'target_project_id': context2.project_id
})
)
self.assertEqual(1, len(self.central_service.find_zones(context1)))
self.assertEqual(1, len(self.central_service.find_zones(context2)))
self.assertEqual(0, len(self.central_service.find_zones(context3)))
# Unshare zone.
self.central_service.unshare_zone(context1, zone['id'], share_zone.id)
self.assertEqual(1, len(self.central_service.find_zones(context1)))
self.assertEqual(0, len(self.central_service.find_zones(context2)))
self.assertEqual(0, len(self.central_service.find_zones(context3)))
def test_share_zone_new_policy_defaults(self):
# Configure designate for enforcing the new policy defaults
self.useFixture(cfg_fixture.Config(cfg.CONF))

View File

@ -0,0 +1,5 @@
---
fixes:
- |
Fixed an issue where zones shared with other projects may not be visible
when a zone list or zone show request is made by the other projects.