mirror of
https://github.com/ansible/awx.git
synced 2026-07-28 00:19:54 -02:30
create new bulk host create endpoint
allow system admins, org admins, and inventory admins to bulk create hosts. Testing on an "open" licensed awx as system admin, I created 1000 hosts with 6 queries in ~ 0.15 seconds Testing on an "open" licensed awx as organization admin, I created 1000 hosts with 11 queries in ~ 0.15 seconds fix org max host check also only do permission denied if license is a trial add /api/v2/bulk to list bulk apis available add api description templates One motiviation to not take a list of hosts with mixed inventories is to keep things simple re: RBAC and keeping a constant number of queries. If there is great clamor for accepting list of hosts to insert into arbitrary different inventories, we could probably make it happen - we'd need to pop the inventory off of each of the hosts, run the HostSerializer validate, then in top level BulkHostCreateSerializer fetch all the inventories/check permissions/org host limits for those inventories/etc. But that makes this that much more complicated. add test for rbac access test also helped me find a bug in a query, fixed that add test to assert num queries scales as expected also move other test to dedicated file also test with super user like I meant to record activity stream for the inventory this records that a certain number of hosts were added by a certain user we could consider if there is any other additional information we want to include
This commit is contained in:
86
awx/main/tests/functional/test_bulk.py
Normal file
86
awx/main/tests/functional/test_bulk.py
Normal file
@@ -0,0 +1,86 @@
|
||||
import pytest
|
||||
|
||||
from uuid import uuid4
|
||||
|
||||
from awx.api.versioning import reverse
|
||||
|
||||
import json
|
||||
from contextlib import contextmanager
|
||||
from django.test.utils import CaptureQueriesContext
|
||||
from django.db import connections
|
||||
|
||||
|
||||
@contextmanager
|
||||
def withAssertNumQueriesLessThan(num_queries):
|
||||
with CaptureQueriesContext(connections['default']) as context:
|
||||
yield
|
||||
fail_msg = f"\r\n{json.dumps(context.captured_queries, indent=4)}"
|
||||
assert len(context.captured_queries) < num_queries, fail_msg
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@pytest.mark.parametrize('num_hosts, num_queries', [(9, 15), (99, 20), (999, 25)])
|
||||
def test_bulk_host_create_num_queries(organization, inventory, post, get, user, num_hosts, num_queries):
|
||||
'''
|
||||
If I am a...
|
||||
org admin
|
||||
inventory admin at org level
|
||||
admin of a particular inventory
|
||||
superuser
|
||||
|
||||
Bulk Host create should take under a certain number of queries
|
||||
'''
|
||||
inventory.organization = organization
|
||||
inventory_admin = user('inventory_admin', False)
|
||||
org_admin = user('org_admin', False)
|
||||
org_inv_admin = user('org_admin', False)
|
||||
superuser = user('admin', True)
|
||||
for u in [org_admin, org_inv_admin, inventory_admin]:
|
||||
organization.member_role.members.add(u)
|
||||
organization.admin_role.members.add(org_admin)
|
||||
organization.inventory_admin_role.members.add(org_inv_admin)
|
||||
inventory.admin_role.members.add(inventory_admin)
|
||||
|
||||
for u in [org_admin, inventory_admin, org_inv_admin, superuser]:
|
||||
hosts = [{'name': uuid4()} for i in range(num_hosts)]
|
||||
with withAssertNumQueriesLessThan(num_queries):
|
||||
bulk_host_create_response = post(reverse('api:bulk_host_create'), {'inventory': inventory.id, 'hosts': hosts}, u, expect=201).data
|
||||
assert bulk_host_create_response['created'] == len(hosts), f"unexpected number of hosts created for user {u}"
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_bulk_host_create_rbac(organization, inventory, post, get, user):
|
||||
'''
|
||||
If I am a...
|
||||
org admin
|
||||
inventory admin at org level
|
||||
admin of a particular invenotry
|
||||
... I can bulk add hosts
|
||||
|
||||
Everyone else cannot
|
||||
'''
|
||||
inventory.organization = organization
|
||||
inventory_admin = user('inventory_admin', False)
|
||||
org_admin = user('org_admin', False)
|
||||
org_inv_admin = user('org_admin', False)
|
||||
auditor = user('auditor', False)
|
||||
member = user('member', False)
|
||||
use_inv_member = user('member', False)
|
||||
for u in [org_admin, org_inv_admin, auditor, member, inventory_admin, use_inv_member]:
|
||||
organization.member_role.members.add(u)
|
||||
organization.admin_role.members.add(org_admin)
|
||||
organization.inventory_admin_role.members.add(org_inv_admin)
|
||||
inventory.admin_role.members.add(inventory_admin)
|
||||
inventory.use_role.members.add(use_inv_member)
|
||||
organization.auditor_role.members.add(auditor)
|
||||
|
||||
for indx, u in enumerate([org_admin, inventory_admin, org_inv_admin]):
|
||||
bulk_host_create_response = post(
|
||||
reverse('api:bulk_host_create'), {'inventory': inventory.id, 'hosts': [{'name': f'foobar-{indx}'}]}, u, expect=201
|
||||
).data
|
||||
assert bulk_host_create_response['created'] == 1, f"unexpected number of hosts created for user {u}"
|
||||
|
||||
for indx, u in enumerate([member, auditor, use_inv_member]):
|
||||
bulk_host_create_response = post(
|
||||
reverse('api:bulk_host_create'), {'inventory': inventory.id, 'hosts': [{'name': f'foobar2-{indx}'}]}, u, expect=400
|
||||
).data
|
||||
Reference in New Issue
Block a user