mirror of
https://github.com/ansible/awx.git
synced 2026-02-27 07:56:06 -03:30
Merge pull request #363 from AlanCoding/org_smart_inv
backend of org-scoped smart inventories
This commit is contained in:
@@ -602,9 +602,20 @@ class InventoryAccess(BaseAccess):
|
||||
|
||||
@check_superuser
|
||||
def can_admin(self, obj, data):
|
||||
# Host filter may only be modified by org admin level
|
||||
org_admin_mandatory = False
|
||||
new_host_filter = data.get('host_filter', None) if data else None
|
||||
if new_host_filter == '': # Provision for field 'blank' behavior
|
||||
new_host_filter = None
|
||||
if new_host_filter != obj.host_filter:
|
||||
org_admin_mandatory = True
|
||||
# Verify that the user has access to the new organization if moving an
|
||||
# inventory to a new organization. Otherwise, just check for admin permission.
|
||||
return self.check_related('organization', Organization, data, obj=obj) and self.user in obj.admin_role
|
||||
return (
|
||||
self.check_related('organization', Organization, data, obj=obj,
|
||||
mandatory=org_admin_mandatory) and
|
||||
self.user in obj.admin_role
|
||||
)
|
||||
|
||||
@check_superuser
|
||||
def can_update(self, obj):
|
||||
|
||||
@@ -37,6 +37,8 @@ class HostManager(models.Manager):
|
||||
hasattr(self.instance, 'kind')):
|
||||
if self.instance.kind == 'smart' and self.instance.host_filter is not None:
|
||||
q = SmartFilter.query_from_string(self.instance.host_filter)
|
||||
if self.instance.organization_id:
|
||||
q = q.filter(inventory__organization=self.instance.organization_id)
|
||||
# If we are using host_filters, disable the core_filters, this allows
|
||||
# us to access all of the available Host entries, not just the ones associated
|
||||
# with a specific FK/relation.
|
||||
|
||||
@@ -10,6 +10,7 @@ from awx.main.models import (
|
||||
InventorySource,
|
||||
InventoryUpdate,
|
||||
)
|
||||
from awx.main.utils.filters import SmartFilter
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -109,3 +110,17 @@ class TestHostManager:
|
||||
organization=organization,
|
||||
host_filter='inventory_sources__source=ec2')
|
||||
assert len(smart_inventory.hosts.all()) == 0
|
||||
|
||||
def test_host_distinctness(self, setup_inventory_groups, organization):
|
||||
"""
|
||||
two criteria would both yield the same host, check that we only get 1 copy here
|
||||
"""
|
||||
assert (
|
||||
list(SmartFilter.query_from_string('name=single_host or name__startswith=single_')) ==
|
||||
[Host.objects.get(name='single_host')]
|
||||
)
|
||||
|
||||
# Things we can not easily test due to SQLite backend:
|
||||
# 2 organizations with host of same name only has 1 entry in smart inventory
|
||||
# smart inventory in 1 organization does not include host from another
|
||||
# smart inventory correctly returns hosts in filter in same organization
|
||||
|
||||
@@ -174,3 +174,17 @@ def test_inventory_source_org_admin_schedule_access(org_admin, inventory_source)
|
||||
assert access.get_queryset()
|
||||
assert access.can_read(schedule)
|
||||
assert access.can_change(schedule, {'rrule': 'DTSTART:20151117T050000Z RRULE:FREQ=DAILY;INTERVAL=1;COUNT=2'})
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def smart_inventory(organization):
|
||||
return organization.inventories.create(name="smart-inv", kind="smart")
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestSmartInventory:
|
||||
|
||||
def test_host_filter_edit(self, smart_inventory, rando, org_admin):
|
||||
assert InventoryAccess(org_admin).can_admin(smart_inventory, {'host_filter': 'search=foo'})
|
||||
smart_inventory.admin_role.members.add(rando)
|
||||
assert not InventoryAccess(rando).can_admin(smart_inventory, {'host_filter': 'search=foo'})
|
||||
|
||||
@@ -220,8 +220,8 @@ class TestHostInsights():
|
||||
class TestInventoryHostsList(object):
|
||||
|
||||
def test_host_list_smart_inventory(self, mocker):
|
||||
Inventory = namedtuple('Inventory', ['kind', 'host_filter', 'hosts'])
|
||||
obj = Inventory(kind='smart', host_filter='localhost', hosts=HostManager())
|
||||
Inventory = namedtuple('Inventory', ['kind', 'host_filter', 'hosts', 'organization_id'])
|
||||
obj = Inventory(kind='smart', host_filter='localhost', hosts=HostManager(), organization_id=None)
|
||||
obj.hosts.instance = obj
|
||||
|
||||
with mock.patch.object(InventoryHostsList, 'get_parent_object', return_value=obj):
|
||||
|
||||
Reference in New Issue
Block a user