Skip to content

Commit

Permalink
add assertion to test on number of queries made (#9)
Browse files Browse the repository at this point in the history
* add assertions around access to resulting job

there is a problem getting the job w/ the user that launched it

add more assertions to bulk tests (#11)

dig more into the results and assert on results
also, use a fixture that already implemented the "max queries" thing

fix ansible collection sanity tests (#12)
  • Loading branch information
kdelee committed Mar 8, 2023
1 parent 7aad169 commit 2becc5d
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 27 deletions.
50 changes: 30 additions & 20 deletions awx/main/tests/functional/test_bulk.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,15 @@

import json
from contextlib import contextmanager
from django.test.utils import CaptureQueriesContext
from django.db import connections
from awx.main.models.jobs import JobTemplate
from awx.main.models import Organization, Inventory


@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
from awx.main.models.jobs import JobTemplate
from awx.main.models import Organization, Inventory, WorkflowJob


@pytest.mark.django_db
@pytest.mark.parametrize('num_hosts, num_queries', [(9, 15), (99, 20), (999, 30)])
def test_bulk_host_create_num_queries(organization, inventory, post, get, user, num_hosts, num_queries):
def test_bulk_host_create_num_queries(organization, inventory, post, get, user, num_hosts, num_queries, django_assert_max_num_queries):
'''
If I am a...
org admin
Expand All @@ -45,7 +37,7 @@ def test_bulk_host_create_num_queries(organization, inventory, post, get, user,

for u in [org_admin, inventory_admin, org_inv_admin, superuser]:
hosts = [{'name': uuid4()} for i in range(num_hosts)]
with withAssertNumQueriesLessThan(num_queries):
with django_assert_max_num_queries(num_queries):
bulk_host_create_response = post(reverse('api:bulk_host_create'), {'inventory': inventory.id, 'hosts': hosts}, u, expect=201).data
assert len(bulk_host_create_response['hosts']) == len(hosts), f"unexpected number of hosts created for user {u}"

Expand Down Expand Up @@ -89,20 +81,36 @@ def test_bulk_host_create_rbac(organization, inventory, post, get, user):


@pytest.mark.django_db
def test_bulk_job_launch(job_template, organization, inventory, project, credential, post, get, user):
@pytest.mark.parametrize('num_jobs, num_queries', [(9, 30), (99, 35)])
def test_bulk_job_launch_queries(job_template, organization, inventory, project, post, get, user, num_jobs, num_queries, django_assert_max_num_queries):
'''
if I have access to the unified job template
... I can launch the bulk job
... and the number of queries should NOT scale with the number of jobs
'''
normal_user = user('normal_user', False)
jt = JobTemplate.objects.create(name='my-jt', inventory=inventory, project=project, playbook='helloworld.yml')
jt.save()
org_admin = user('org_admin', False)
jt = JobTemplate.objects.create(name='my-jt', ask_inventory_on_launch=True, project=project, playbook='helloworld.yml')
organization.member_role.members.add(normal_user)
organization.admin_role.members.add(org_admin)
jt.execute_role.members.add(normal_user)
bulk_job_launch_response = post(
reverse('api:bulk_job_launch'), {'name': 'Bulk Job Launch', 'jobs': [{'unified_job_template': jt.id}]}, normal_user, expect=201
).data
assert bulk_job_launch_response['id'] == 1
inventory.use_role.members.add(normal_user)
jt.save()
inventory.save()
jobs = [{'unified_job_template': jt.id, 'inventory': inventory.id} for _ in range(num_jobs)]

# This is not working, we need to figure that out if we want to include tests for more jobs
# with mock.patch('awx.api.serializers.settings.BULK_JOB_MAX_LAUNCH', num_jobs + 1):
with django_assert_max_num_queries(num_queries):
bulk_job_launch_response = post(reverse('api:bulk_job_launch'), {'name': 'Bulk Job Launch', 'jobs': jobs}, normal_user, expect=201).data

for u in (org_admin,): # TODO normal_user not working because launched_by not getting set in the tests...does happen in real request
bulk_job = get(bulk_job_launch_response['url'], u, expect=200).data
assert organization.id == bulk_job['summary_fields']['organization']['id']
resp = get(bulk_job_launch_response['related']['workflow_nodes'], u)
assert resp.data['count'] == num_jobs
for item in resp.data['results']:
assert item["unified_job_template"] == jt.id


@pytest.mark.django_db
Expand Down Expand Up @@ -167,7 +175,9 @@ def test_bulk_job_launch_specific_org(job_template, organization, inventory, pro
bulk_job_launch_response = post(
reverse('api:bulk_job_launch'), {'name': 'Bulk Job Launch', 'jobs': [{'unified_job_template': jt.id}], 'organization': org1.id}, normal_user, expect=201
).data
assert bulk_job_launch_response['id'] == 1
bulk_job_id = bulk_job_launch_response['id']
bulk_job_obj = WorkflowJob.objects.filter(id=bulk_job_id, is_bulk_job=True).first()
assert org1.id == bulk_job_obj.organization.id


@pytest.mark.django_db
Expand Down
1 change: 1 addition & 0 deletions awx_collection/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ Notable releases of the `awx.awx` collection:
- 7.0.0 is intended to be identical to the content prior to the migration, aside from changes necessary to function as a collection.
- 11.0.0 has no non-deprecated modules that depend on the deprecated `tower-cli` [PyPI](https://pypi.org/project/ansible-tower-cli/).
- 19.2.1 large renaming purged "tower" names (like options and module names), adding redirects for old names
- 21.11.0 "tower" modules deprecated and symlinks removed.
- 0.0.1-devel is the version you should see if installing from source, which is intended for development and expected to be unstable.

The following notes are changes that may require changes to playbooks:
Expand Down
8 changes: 4 additions & 4 deletions awx_collection/plugins/modules/bulk_host_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
description:
- The name to use for the host.
type: str
require: True
required: True
description:
description:
- The description to use for the host.
Expand Down Expand Up @@ -70,7 +70,7 @@
def main():
# Any additional arguments that are not fields of the item can be added here
argument_spec = dict(
hosts=dict(required=True, type='list'),
hosts=dict(required=True, type='list', elements='dict'),
inventory=dict(required=True, type='int'),
)

Expand All @@ -82,8 +82,8 @@ def main():
hosts = module.params.get('hosts')

for h in hosts:
if 'variables' in h:
h['variables'] = json.dumps(h['variables'])
if 'variables' in h:
h['variables'] = json.dumps(h['variables'])
# Launch the jobs
result = module.post_endpoint("bulk/host_create", data={"inventory": inventory, "hosts": hosts})

Expand Down
3 changes: 1 addition & 2 deletions awx_collection/plugins/modules/bulk_job_launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@
def main():
# Any additional arguments that are not fields of the item can be added here
argument_spec = dict(
jobs=dict(required=True, type='list'),
jobs=dict(required=True, type='list', elements='dict'),
name=dict(),
description=dict(),
organization=dict(type='int'),
Expand All @@ -217,7 +217,6 @@ def main():
skip_tags=dict(),
wait=dict(required=False, default=True, type='bool'),
interval=dict(required=False, default=2.0, type='float'),
timeout=dict(required=False, default=None, type='int'),
)

# Create a module for ourselves
Expand Down
3 changes: 2 additions & 1 deletion awx_collection/test/awx/test_bulk.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from awx.main.models import WorkflowJob


@pytest.mark.django_db
def test_bulk_job_launch(run_module, admin_user, job_template):
jobs = [dict(unified_job_template=job_template.id)]
Expand Down Expand Up @@ -39,4 +40,4 @@ def test_bulk_host_create(run_module, admin_user, inventory):
)
resp_hosts = inventory.hosts.all().values_list('name', flat=True)
for h in hosts:
assert h['name'] in resp_hosts
assert h['name'] in resp_hosts

0 comments on commit 2becc5d

Please sign in to comment.