From 98d3f3dc8af1dcc7a843d2881aba54c0cab42de4 Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Mon, 28 Oct 2019 09:58:00 -0400 Subject: [PATCH] Add tests for AWX collection credential fixes (#3893) --- awx/main/tests/functional/api/test_generic.py | 7 ++ awx/main/tests/functional/conftest.py | 13 +++- awx_collection/README.md | 19 +++++ awx_collection/test/awx/test_job_template.py | 1 - awx_collection/test/awx/test_send_receive.py | 72 +++++++++++++++++++ 5 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 awx_collection/test/awx/test_send_receive.py diff --git a/awx/main/tests/functional/api/test_generic.py b/awx/main/tests/functional/api/test_generic.py index e956475e2d..c6fe7ca188 100644 --- a/awx/main/tests/functional/api/test_generic.py +++ b/awx/main/tests/functional/api/test_generic.py @@ -117,3 +117,10 @@ def test_handle_content_type(post, admin): admin, content_type='text/html', expect=415) + + +@pytest.mark.django_db +def test_basic_not_found(get, admin_user): + root_url = reverse('api:api_v2_root_view') + r = get(root_url + 'fooooooo', user=admin_user, expect=404) + assert r.data.get('detail') == 'The requested resource could not be found.' diff --git a/awx/main/tests/functional/conftest.py b/awx/main/tests/functional/conftest.py index d8ae10f902..ee44aad84a 100644 --- a/awx/main/tests/functional/conftest.py +++ b/awx/main/tests/functional/conftest.py @@ -8,6 +8,8 @@ from unittest.mock import PropertyMock # Django from django.urls import resolve +from django.http import Http404 +from django.core.handlers.exception import response_for_exception from django.contrib.auth.models import User from django.core.serializers.json import DjangoJSONEncoder from django.db.backends.sqlite3.base import SQLiteCursorWrapper @@ -581,8 +583,12 @@ def _request(verb): if 'format' not in kwargs and 'content_type' not in kwargs: kwargs['format'] = 'json' - view, view_args, view_kwargs = resolve(urllib.parse.urlparse(url)[2]) request = getattr(APIRequestFactory(), verb)(url, **kwargs) + request_error = None + try: + view, view_args, view_kwargs = resolve(urllib.parse.urlparse(url)[2]) + except Http404 as e: + request_error = e if isinstance(kwargs.get('cookies', None), dict): for key, value in kwargs['cookies'].items(): request.COOKIES[key] = value @@ -591,7 +597,10 @@ def _request(verb): if user: force_authenticate(request, user=user) - response = view(request, *view_args, **view_kwargs) + if not request_error: + response = view(request, *view_args, **view_kwargs) + else: + response = response_for_exception(request, request_error) if middleware: middleware.process_response(request, response) if expect: diff --git a/awx_collection/README.md b/awx_collection/README.md index 1a1a1e1a62..2340ed4336 100644 --- a/awx_collection/README.md +++ b/awx_collection/README.md @@ -40,6 +40,8 @@ in `awx_collection/test/awx`. These tests require that python packages are available for all of `awx`, `ansible`, `tower_cli`, and the collection itself. +### Inside Development Container + The target `make prepare_collection_venv` will prepare some requirements in the `awx_collection_test_venv` folder so that `make test_collection` can be ran to actually run the tests. A single test can be ran via: @@ -48,6 +50,23 @@ be ran to actually run the tests. A single test can be ran via: make test_collection COLLECTION_TEST_DIRS=awx_collection/test/awx/test_organization.py ``` +### Manually + +As a faster alternative if you do not want to use the container, or +run against Ansible or tower-cli source, it is possible to set up a +working environment yourself. + +``` +mkvirtualenv my_new_venv +# may need to replace psycopg2 with psycopg2-binary in requirements/requirements.txt +pip install -r requirements/requirements.txt -r requirements/requirements_dev.txt -r requirements/requirements_git.txt +make clean-api +pip install -e +pip install -e +pip install -e . +PYTHONPATH=awx_collection:$PYTHONPATH py.test awx_collection/test/awx/ +``` + ## Building The build target `make build_collection` will template out a `galaxy.yml` file diff --git a/awx_collection/test/awx/test_job_template.py b/awx_collection/test/awx/test_job_template.py index e5ecfeb793..9c5764b61c 100644 --- a/awx_collection/test/awx/test_job_template.py +++ b/awx_collection/test/awx/test_job_template.py @@ -32,7 +32,6 @@ def test_create_job_template(run_module, admin_user, project, inventory): @pytest.mark.django_db -@pytest.mark.xfail(reason='Known limitation and needs to be fixed.') def test_create_job_template_with_old_machine_cred(run_module, admin_user, project, inventory, machine_credential): module_args = { diff --git a/awx_collection/test/awx/test_send_receive.py b/awx_collection/test/awx/test_send_receive.py new file mode 100644 index 0000000000..67ced22833 --- /dev/null +++ b/awx_collection/test/awx/test_send_receive.py @@ -0,0 +1,72 @@ +import pytest +import json + +from awx.main.models import ( + Organization, + Project, + Inventory, + Host, + CredentialType, + Credential, + JobTemplate +) + + +@pytest.mark.django_db +def test_receive_send_jt(run_module, admin_user, mocker): + org = Organization.objects.create(name='SRtest') + proj = Project.objects.create( + name='SRtest', + playbook_files=['debug.yml'], + scm_type='git', + scm_url='https://github.com/ansible/test-playbooks.git', + organization=org, + allow_override=True # so we do not require playbooks populated + ) + inv = Inventory.objects.create(name='SRtest', organization=org) + Host.objects.create(name='SRtest', inventory=inv) + ct = CredentialType.defaults['ssh']() + ct.save() + cred = Credential.objects.create( + name='SRtest', + credential_type=ct, + organization=org + ) + jt = JobTemplate.objects.create( + name='SRtest', + project=proj, + inventory=inv, + playbook='helloworld.yml' + ) + jt.credentials.add(cred) + jt.admin_role.members.add(admin_user) # work around send/receive bug + + # receive everything + result = run_module('tower_receive', dict(all=True), admin_user) + + assert 'assets' in result, result + assets = result['assets'] + assert not result.get('changed', True) + assert set(a['asset_type'] for a in assets) == set(( + 'organization', 'inventory', 'job_template', 'credential', 'project', + 'user' + )) + + # delete everything + for obj in (jt, inv, proj, cred, org): + obj.delete() + + def fake_wait(self, pk, parent_pk=None, **kwargs): + return {"changed": True} + + # recreate everything + with mocker.patch('sys.stdin.isatty', return_value=True): + with mocker.patch('tower_cli.models.base.MonitorableResource.wait'): + result = run_module('tower_send', dict(assets=json.dumps(assets)), admin_user) + + assert not result.get('failed'), result + + new = JobTemplate.objects.get(name='SRtest') + assert new.project.name == 'SRtest' + assert new.inventory.name == 'SRtest' + assert [cred.name for cred in new.credentials.all()] == ['SRtest']