diff --git a/.coveragerc b/.coveragerc index d7a734c1d6..f9ef3447bf 100644 --- a/.coveragerc +++ b/.coveragerc @@ -25,3 +25,5 @@ exclude_lines = ignore_errors = True +[xml] +output = ./reports/coverage.xml diff --git a/Makefile b/Makefile index a9f0cc557d..435b059388 100644 --- a/Makefile +++ b/Makefile @@ -155,7 +155,7 @@ endif .PHONY: clean rebase push requirements requirements_dev requirements_jenkins \ real-requirements real-requirements_dev real-requirements_jenkins \ develop refresh adduser syncdb migrate dbchange dbshell runserver celeryd \ - receiver test test_coverage coverage_html test_jenkins dev_build \ + receiver test test_unit test_coverage coverage_html test_jenkins dev_build \ release_build release_clean sdist rpmtar mock-rpm mock-srpm rpm-sign \ build-ui sync-ui test-ui build-ui-for-coverage test-ui-for-coverage \ build-ui-for-browser-tests test-ui-debug jshint ngdocs \ @@ -357,14 +357,17 @@ pylint: reports @(set -o pipefail && $@ | reports/$@.report) check: flake8 pep8 # pyflakes pylint - + # Run all API unit tests. test: - $(PYTHON) manage.py test -v2 awx.main.tests + py.test awx/main/tests awx/api/tests awx/fact/tests + +test_unit: + py.test awx/main/tests/unit # Run all API unit tests with coverage enabled. test_coverage: - coverage run manage.py test -v2 awx.main.tests + py.test --cov=awx --cov-report=xml --junitxml=./reports/junit.xml awx/main/tests awx/api/tests awx/fact/tests # Output test coverage as HTML (into htmlcov directory). coverage_html: @@ -375,8 +378,8 @@ test_tox: tox -v # Run unit tests to produce output for Jenkins. -test_jenkins: - $(PYTHON) manage.py jenkins -v2 --enable-coverage --project-apps-tests +# Alias existing make target so old versions run against Jekins the same way +test_jenkins : test_coverage # UI TASKS # -------------------------------------- diff --git a/awx/api/tests/job_tasks.py b/awx/api/tests/job_tasks.py index 36c7eb6fb0..93861f8d56 100644 --- a/awx/api/tests/job_tasks.py +++ b/awx/api/tests/job_tasks.py @@ -5,7 +5,7 @@ from django.conf import settings from django.test import LiveServerTestCase from django.test.utils import override_settings -from awx.main.tests.jobs import BaseJobTestMixin +from awx.main.tests.job_base import BaseJobTestMixin @override_settings(CELERY_ALWAYS_EAGER=True, diff --git a/awx/fact/tests/utils/dbtransform.py b/awx/fact/tests/utils/dbtransform.py index 97bfad9c65..5f0eb1ad24 100644 --- a/awx/fact/tests/utils/dbtransform.py +++ b/awx/fact/tests/utils/dbtransform.py @@ -1,15 +1,16 @@ # Copyright (c) 2015 Ansible, Inc. # All Rights Reserved +from django.test import TestCase + # AWX -from awx.main.tests.base import BaseTest from awx.fact.models.fact import * # noqa from awx.fact.utils.dbtransform import KeyTransform #__all__ = ['DBTransformTest', 'KeyTransformUnitTest'] __all__ = ['KeyTransformUnitTest'] -class KeyTransformUnitTest(BaseTest): +class KeyTransformUnitTest(TestCase): def setUp(self): super(KeyTransformUnitTest, self).setUp() self.key_transform = KeyTransform([('.', '\uff0E'), ('$', '\uff04')]) @@ -82,7 +83,7 @@ class KeyTransformUnitTest(BaseTest): data = self.key_transform.transform_incoming(value, None) self.assertEqual(data, value_transformed) - + data = self.key_transform.transform_outgoing(value_transformed, None) self.assertEqual(data, value) @@ -103,7 +104,7 @@ class KeyTransformUnitTest(BaseTest): } data = self.key_transform.transform_incoming(value, None) self.assertEqual(data, value_transformed) - + data = self.key_transform.transform_outgoing(value_transformed, None) self.assertEqual(data, value) diff --git a/awx/main/access.py b/awx/main/access.py index de2f69a914..ad87506ab2 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -149,7 +149,7 @@ class BaseAccess(object): def check_license(self, add_host=False, feature=None, check_expiration=True): reader = TaskSerializer() validation_info = reader.from_database() - if ('test' in sys.argv or 'jenkins' in sys.argv) and not os.environ.get('SKIP_LICENSE_FIXUP_FOR_TEST', ''): + if ('test' in sys.argv or 'py.test' in sys.argv[0] or 'jenkins' in sys.argv) and not os.environ.get('SKIP_LICENSE_FIXUP_FOR_TEST', ''): validation_info['free_instances'] = 99999999 validation_info['time_remaining'] = 99999999 validation_info['grace_period_remaining'] = 99999999 @@ -912,8 +912,8 @@ class JobTemplateAccess(BaseAccess): ) return base_qs.filter( - Q(id__in=org_admin_ids) | - Q(id__in=perm_deploy_ids) | + Q(id__in=org_admin_ids) | + Q(id__in=perm_deploy_ids) | Q(id__in=perm_check_ids) ) @@ -926,7 +926,7 @@ class JobTemplateAccess(BaseAccess): a user can create a job template if they are a superuser, an org admin of any org that the project is a member, or if they have user or team based permissions tying the project to the inventory source for the - given action as well as the 'create' deploy permission. + given action as well as the 'create' deploy permission. Users who are able to create deploy jobs can also run normal and check (dry run) jobs. ''' if not data or '_method' in data: # So the browseable API will work? @@ -1126,8 +1126,8 @@ class JobAccess(BaseAccess): ) return base_qs.filter( - Q(id__in=org_admin_ids) | - Q(id__in=perm_deploy_ids) | + Q(id__in=org_admin_ids) | + Q(id__in=perm_deploy_ids) | Q(id__in=perm_check_ids) ) @@ -1367,9 +1367,9 @@ class UnifiedJobTemplateAccess(BaseAccess): projects without SCM configured or inventory sources without a cloud source. ''' - + model = UnifiedJobTemplate - + def get_queryset(self): qs = self.model.objects.filter(active=True).distinct() project_qs = self.user.get_queryset(Project).filter(scm_type__in=[s[0] for s in Project.SCM_TYPE_CHOICES]) diff --git a/awx/main/models/credential.py b/awx/main/models/credential.py index a1deb7053f..8f0d32d87a 100644 --- a/awx/main/models/credential.py +++ b/awx/main/models/credential.py @@ -1,7 +1,6 @@ # Copyright (c) 2015 Ansible, Inc. # All Rights Reserved. -# Python import base64 import re @@ -471,3 +470,4 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique): if 'cloud' not in update_fields: update_fields.append('cloud') super(Credential, self).save(*args, **kwargs) + diff --git a/awx/main/tests/__init__.py b/awx/main/tests/__init__.py index 4f1e89274e..e69de29bb2 100644 --- a/awx/main/tests/__init__.py +++ b/awx/main/tests/__init__.py @@ -1,22 +0,0 @@ -# Copyright (c) 2015 Ansible, Inc. -# All Rights Reserved. - -from awx.main.tests.organizations import * # noqa -from awx.main.tests.users import * # noqa -from awx.main.tests.inventory import * # noqa -from awx.main.tests.projects import ProjectsTest, ProjectUpdatesTest # noqa -from awx.main.tests.commands import * # noqa -from awx.main.tests.scripts import * # noqa -from awx.main.tests.tasks import RunJobTest # noqa -from awx.main.tests.ad_hoc import * # noqa -from awx.main.tests.licenses import LicenseTests # noqa -from awx.main.tests.jobs import * # noqa -from awx.main.tests.activity_stream import * # noqa -from awx.main.tests.schedules import * # noqa -from awx.main.tests.redact import * # noqa -from awx.main.tests.views import * # noqa -from awx.main.tests.commands import * # noqa -from awx.main.tests.fact import * # noqa -from awx.main.tests.unified_jobs import * # noqa -from awx.main.tests.ha import * # noqa -from awx.main.tests.settings import * # noqa diff --git a/awx/main/tests/commands/__init__.py b/awx/main/tests/commands/__init__.py deleted file mode 100644 index 84212dd2fb..0000000000 --- a/awx/main/tests/commands/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2015 Ansible, Inc. -# All Rights Reserved - -from __future__ import absolute_import - -from .run_fact_cache_receiver import * # noqa -from .commands_monolithic import * # noqa -from .cleanup_facts import * # noqa -from .age_deleted import * # noqa -from .remove_instance import * # noqa -from .run_socketio_service import * # noqa -from .update_password import * # noqa - diff --git a/awx/main/tests/data/__init__.py b/awx/main/tests/data/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/awx/main/tests/data/ssh.py b/awx/main/tests/data/ssh.py new file mode 100644 index 0000000000..ff5592358e --- /dev/null +++ b/awx/main/tests/data/ssh.py @@ -0,0 +1,169 @@ +TEST_SSH_KEY_DATA = '''-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAyQ8F5bbgjHvk4SZJsKI9OmJKMFxZqRhvx4LaqjLTKbBwRBsY +1/C00NPiZn70dKbeyV7RNVZxuzM6yd3D3lwTdbDu/eJ0x72t3ch+TdLt/aenyy10 +IvZyhSlxCLDkDaVVPFYJOQzVS8TkdOi6ZHc+R0c0A+4ZE8OQ8C0zIKtUTHqRk4/v +gYK5guhNS0DdgWkBj6K+r/9D4bqdPTJPt4S7H75vb1tBgseiqftEkLYOhTK2gsCi +5uJgpG4zPQY4Kk/97dbW7pwcvPkr1rKkAwEJ27Bfo+DBv3oEx3SinpXQtOrH1aEO +RHSXldBaymdBtVLUhjxDlnnQ7Ps+fNX04R7N4QIDAQABAoIBAQClEDxbNyRqsVxa +q8BbzxZNVFxsD6Vceb9rIDa8/DT4SO4iO8zNm8QWnZ2FYDz5d/X3hGxlSa7dbVWa +XQJtD1K6kKPks4IEaejP58Ypxj20vWu4Fnz+Jy4lvLwb0n2n5lBv1IKF389NATw9 +7sL3sB3lDsPZZiQYYbogNDuBWqc+kP0zD84bONsM/B2HMRm9BRv2UsZf+zKU4pTA +UqHffyjmw7LqHmbtVjwVcUsC+xcE4kCuWLvabFnTWOSnWECyIw2+trxKdwCXbfzG +s5rn4Dj+aEKimzFaRpTSVx6w4yw9xw/EjsSaZ88jKSpTP8ocCut6zv+P/JwlukEX +4A4FxqyxAoGBAOp3G9EIAAWijcIgO5OdiZNEqVyqd3yyPzT6d/q7bf4dpVCZiLNA +bRmge83aMc4g2Dpkn/++It3bDmnXXGg+BZSX5KT9JLklXchaw9phv9J0diZEUvYS +mSQafbUGIqYnYzns3TU0cbgITs1iVIEstHYjGr3J88nDG+HFCHboxa93AoGBANuG +cDFgyvm79+haK2fHhUCZgaFFYBpkpuz+zjDjzIytOzymWa2gD9jIa7mvdvoH2ge3 +AVG0vy+n9cJaqJMuLkhdI01wVlqY9wvDHFyZCXyIvKVPMljKeTvCNGCupsG4R171 +gSKT5ryOx58MGbE7knAZC+QWpwxFpdpbfej6g7NnAoGBAMz6ipAJbXN/tG0FnvAj +pxXfzizcPw/+CTI40tGaMMQbiN5ZC+CiL39bBUFnQ2mQ31jVheegg3zvuL8hb4EW +z+wjitoPEZ7nowC5EUaHdJr6BBzaWKkWg1nD6yhqj7ow7xfCE3YjPlQEt1fpYjV4 +LuClOgi4WPCIKYUMq6TBRaprAoGAVrEjs0xPPApQH5EkXQp9BALbH23/Qs0G4sbJ +dKMxT0jGAPCMr7VrLKgRarXxXVImdy99NOAVNGO2+PbGZcEyA9/MJjO71nFb9mgp +1iOVjHmPThUVg90JvWC3QIsYTZ5RiR2Yzqfr0gDsslGb/9LPxLcPbBbKB12l3rKM +6amswvcCgYEAvgcSlTfAkI3ac8rB70HuDmSdqKblIiQjtPtT/ixXaFkZOmHRr4AE +KepMRDnaO/ldPDPEWCGqPzEM0t/0jS8/hCu3zLHHpZ+0LnHq+EXkOI0/GB4P+z5l +Vz3kouC0BTav0rCEnDop/cWMTiAp/XhKXfrTTTOra/F8l2xD8n/mnzY= +-----END RSA PRIVATE KEY-----''' + +TEST_SSH_KEY_DATA_LOCKED = '''-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,6B4E92AF4C29DE26FD8535D81825BDE6 + +pg8YplxPpfzgEGUiko34DGaYklyGyYKXjOrGFGyLoquNAVNFyewT34dDrZi0IAaE +79wMVcdlHbrJfZz8ML8I/ft6zM6BdlwZExH4y9DRAaktY3yIXxSvowBQ6ljh3wUy +M6m0afOfVjT22V8hLFgX0yTQ6P9zTG1cmj6+JQWTsMJ5EP3rnFK5CyrJXP48B3GI +GgE66rkXDvcKlVeIrbrpcTyfmEpafPgVRJYCDFXxeO/BfKgUFVxFq1PgFbvGQMmD +wA6EsyRrN+aoub1sqzj8tM8e4nwEi0EifdRShkFeqH4GUOKypanTXfCqwFBgYi5a +i3YwSnniZZPwCniGR5cl8oetrc5dubq/IR0txsGi2lO6zJEWdSer/EadS0QAll4S +yXrSc/lFaez1VmVe/8aoBKDOHhe7jV3YXAuqCeB4o/SThB/9Gad44MTbqFH3d7cD +k+F0Cjup7LZqZpXeB7ZHRG/Yt9MtBzwDVmEWaxA1WIN5a8xyZEVzRswSi4lZX69z +Va7eTKcrCbHOQmIbLZGRiZbAbfgriwwxQCJWELv80h+A754Bhi23n3WzcT094fRi +cqK//HcHHXxYGmrfUbHYcj+GCQ07Uk2ZR3qglmPISUCgfZwM9k0LpXudWE8vmF2S +pAnbgxgrfUMtpu5EAO+d8Sn5wQLVD7YzPBUhM4PYfYUbJnRoZQryuR4lqCzcg0te +BM8x1LzSXyBEbQaonuMzSz1hCQ9hZpUwUEqDWAT3cPNmgyWkXQ1P8ehJhTmryGJw +/GHxNzMZDGj+bBKo7ic3r1g3ZmmlSU1EVxMLvRBKhdc1XicBVqepDma6/LEpj+5X +oplR+3Q0QSQ8CchcSxYtOpI3UBCatpyu09GtfzS+7bI5I7FVYUccR83+oQlKpPHC +5O2irB8JeXqAY679fx2N4i0E6l5Xr5AjUtOBCNil0Y70eOf9ER6i7kGakR7bUtk5 +fQn8Em9pLsYYalnekn4sxyHpGq59KgNPjQiJRByYidSJ/oyNbmtPlxfXLwpuicd2 +8HLm1e0UeGidfF/bSlySwDzy1ZlSr/Apdcn9ou5hfhaGuQvjr9SvJwxQFNRMPdHj +ukBSDGuxyyU+qBrWJhFsymiZAWDofY/4GzgMu4hh0PwN5arzoTxnLHmc/VFttyMx +nP7bTaa9Sr54TlMr7NuKTzz5biXKjqJ9AZKIUF2+ERebjV0hMpJ5NPsLwPUnA9kx +R3tl1JL2Ia82ovS81Ghff/cBZsx/+LQYa+ac4eDTyXxyg4ei5tPwOlzz7pDKJAr9 +XEh2X6rywCNghEMZPaOQLiEDLJ2is6P4OarSa/yoU4OMetpFfwZ0oJSCmGlEa+CF +zeJ80yXhU1Ru2eqiUjCAUg25BFPwoiMJDc6jWWow7OrXCQsw7Ddo2ncy1p9QeWjM +2R4ojPHWuXKYxvwVSc8NZHASlycBCaxHLDAEyH4avOSDPWOB1H5t+RrNmo0qgush +0aRo6F7BjzB2rA4E+xu2u11TBfF8iB3PC919/vxnkXF97NqezsaCz6VbRlsU0A+B +wwoi+P4JlJF6ZuhuDv6mhmBCSdXdc1bvimvdpOljhThr+cG5mM08iqWGKdA665cw +-----END RSA PRIVATE KEY----- +''' + +TEST_OPENSSH_KEY_DATA = '''-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn +NhAAAAAwEAAQAAAQEA1AZAwUJUiLmOXjbO5q2ZE5DF+gMpPKe8NEr12FpvOaJr1Nz/DNpf +FE/VbssOJ4CRD/6MItlPSG2pC1Cv3AYSL7NBc0YCMlBR/P/nLI8pLAzU3p3KRYvR+R6cMW +3nMcxyB1UUgzXY9dTVFIyejOsm7stGuNfdDTTLBE2vTDz6CyzxxSALEOdYut5cfeTUuG7d +nP01K3JiaHjHaXDmwraRR/JlitylaZUnSZ+/b9WCMX5FyeJ6CnGdvcCuvMK0iNjZ8R+PxP +xJBM5AlJC5J6qa8YmeaQ6lA/2S+/wGuhJmocmiXiLFy9IzIPnQiR+h8DqStp4xp245UQxe +TIGSMmq8DQAAA9A4FMRSOBTEUgAAAAdzc2gtcnNhAAABAQDUBkDBQlSIuY5eNs7mrZkTkM +X6Ayk8p7w0SvXYWm85omvU3P8M2l8UT9Vuyw4ngJEP/owi2U9IbakLUK/cBhIvs0FzRgIy +UFH8/+csjyksDNTencpFi9H5HpwxbecxzHIHVRSDNdj11NUUjJ6M6ybuy0a4190NNMsETa +9MPPoLLPHFIAsQ51i63lx95NS4bt2c/TUrcmJoeMdpcObCtpFH8mWK3KVplSdJn79v1YIx +fkXJ4noKcZ29wK68wrSI2NnxH4/E/EkEzkCUkLknqprxiZ5pDqUD/ZL7/Aa6EmahyaJeIs +XL0jMg+dCJH6HwOpK2njGnbjlRDF5MgZIyarwNAAAAAwEAAQAAAQAp8orBMYRUAJIgJavN +i67rZgslKZbw/yaHGgWFpm628mFvHcIAIvwIorrRTq8gNZl9lpjXFDNRWxDEwlPorfLPKS +Hb0pAAsE9oRKDR+gjlRCyhVop8M+t45At25A2HlrFArh5+zxp7mH4HsMJ1ktiDCgiV7W84 +e6dm1I/H/5BgwUlTNoVOGPrU183gqRsHIICjfmnjl2ObJoly+MTrAy7E9rSmsO+pHKl8z0 +XODWh3mo+EkCoYrK6kP96Jy3BepSmbZMROEsctS7Mkzu6QdnfTY3QqIzENYtTGJuAGktGj +su4MHP8hbj+TznNkFeZdmIC0uTnIKu1uquwuFF1HPZiBAAAAgACX9xPKS2J04WXpQag+JS +06n2zSuBHW7Kq4q/LMydoTRd8Quf6u6eivSBrl7H779LCtGCIZqJAslvWOyPyz2CohcCBU +emubiHcUA+aN7R9E0tyitwWraJjMIwpQ7+AbgdsLsuxozNeccSrr0tva2c5y9x7YGBcIdC +UJDt4xnBi7AAAAgQDz771v8Mb18kq5W+inDcYPFUNXGtNfeYZEOhYFpxunFnYwTEAG0Xnh +YpQXOAFZ2q5mkFQHMl4cOKwoAlaP0dM4v0JKPjFDLvGisEu95fnivj4YAMP/UHgKKxBbqW +HPUhg3adAmIJ9z9u/VmTErbVklcKWlyZuTUkxeQ/BJmSIRUQAAAIEA3oKAzdDURjy8zxLX +gBLCPdi8AxCiqQJBCsGxXCgKtZewset1XJHIN9ryfb4QSZFkSOlm/LgdeGtS8Or0GNPRYd +hgnUCF0LkEsDQ7HzPZYujLrAwjumvGQH6ORp5vRh0tQb93o4e1/A2vpdSKeH7gCe/jfUSY +h7dFGNoAI4cF7/0AAAAUcm9vdEBwaWxsb3cuaXhtbS5uZXQBAgMEBQYH +-----END OPENSSH PRIVATE KEY----- +''' + +TEST_OPENSSH_KEY_DATA_LOCKED = '''-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABALaWMfjc +hSvC7aXxQs1ZDiAAAAEAAAAAEAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQDEDWKwZD8+ +h+2gZZKna8dy2QL4jJxM1eLGDcQDnuip1ixhaf5MT5T6BMploXXHs1pfuwx8yTQ6Ts/VJp +WX6cuHQg8sPGM3P7HNGUqs9q/EQfrrRxz555uL08CRaS6FjM/6x9iolNhHU910Wlg+R+ZS +xiMrrY/s03EiEChsAWTbwBGqTopGC2xMFgIxINoQtTFXv7MtCbDfl8aWKQRDmzkLvwT07N +ycj2kqADqoukD/2bQvPrW6FIZPJPpAdeAe2SZbf/y92NgVz/glOdtjaJp3oqn1QHrOA9/k +XgXOjgVQUbzX7qyLWenxM138VsRKUJZeROaHt1MWApLrLtKQ36SrAAAD0A+PODJjfeKm3U +JknlSYD7fFh6bVZGwG6LnLMtobs0elOfj2+sdg+hOVqyrA0rPOHES5yGKslTc/wRkRQ95m +dBleAyTDIOQ90IqDxT3lsNQwpscsFKPYKGmaUvZLLk4aNY1GeANtByXwTsjetVqn8Uo59A +zu6phX8Aagn2h0qxQwBnDjlzsXf6g5H7UPZd/t1dYr1NfVP6KWJrg0jivAI8tzO2HcM9W2 +cyOaodBw/6TsJNKvDV714Z+apvrNDEufBUsovKjAna2BDVZIhTCg5mYm0Dks8JStQrG2S1 +Yk8EM3+fpo8uMoHVz1jbYC8UX12pwIU67MhUn24KBxqulCYaTMsrLFkNWk6vKgwib+sIa4 +i1Bij1Zd0rdJWypQqTc2Oj3bBSYM47AksMXcKVpuNnFLh4+eokpQzbtIYpRqhOTh1Fky7z +xkhTgWVvf/F19M9t1bz3Rm1/t5I75Ag9qfKWs06j+VVfXnDt5v5hYAEhoJjMzSjgKaqc5g +YndeWeUwO6Vijt4XpkB8+0R7Kptsh9L0UUsNIcRoGcqrM8IUVb3D8vPWppPlj9d6LB+FCo +Cy1JlscnpBb8AQy9QMvrJTHKOyjRcenVxILPiN8PypIC008jvqpDzKimAxM4IMuA7AWE6w +j5+CzfUhDAJGdl2qH/nVc7GFUtz8bVA/v9Zkawg2MLcafgGollbLcTbKwDFcenQuyHT+Hj +uDm2f0oV/EDKFqLijlV8vcLBNUZoxY/L62Vora1jlqnapq2Z/AM9NicoELYNe21ReJ5dxM +7Pk/QdSrZjQzxoHf8uBDpb7x/KyfnSdf8GmdGCxoJ5mcepwD4tROMFC104tN0STJpdGVSm +Q5ZG1JDN7F9iJCCAwyulWH/XxTzFYnQ84199cQeV/M9rXXgbXa8ApAung6X9j8y1fcw9Lw +wV1aP06bCNgM0U50PiZ54HXwzVt+Ghs06TEF4/ZQiIgNJxdw0HFxAJj8qHqUCHuSmvBgnN +qRW/uruItwpXLaL00EHu7rAFlBi1BnnetI+D12ls04mlyTUFFM5v520B5zPV+5If2hx91w +C6Oxl1Wsp3gPkK2yiuy8qcrvoEoJ25TeEhUGEAPWx2OuQJO/Lpq9aF/JJoqGwnBaXdCsi+ +5ig+ZMq5GKQtyydzyXImjlNEUH1w2prRDiGVEufANA5LSLCtqOLgDzXS62WUBjJBrQJVAM +YpWz1tiZQoyv1RT3Y0O0Vwe2Z5AK3fVM0I5jWdiLrIErtcR4ULa6T56QtA52DufhKzINTR +Vg9TtUBqfKIpRQikPSjm7vpY/Xnbc= +-----END OPENSSH PRIVATE KEY----- +''' + +TEST_SSH_CERT_KEY = """-----BEGIN CERTIFICATE----- +MIIDNTCCAh2gAwIBAgIBATALBgkqhkiG9w0BAQswSTEWMBQGA1UEAwwNV2luZG93 +cyBBenVyZTELMAkGA1UEBhMCVVMxIjAgBgkqhkiG9w0BCQEWE2x1a2VAc25lZXJp +bmdlci5jb20wHhcNMTQwNzI4MTQzMjExWhcNMTUwNzI4MTQzMjExWjBJMRYwFAYD +VQQDDA1XaW5kb3dzIEF6dXJlMQswCQYDVQQGEwJVUzEiMCAGCSqGSIb3DQEJARYT +bHVrZUBzbmVlcmluZ2VyLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL9UHMhmAkbEJtg7jxAYjRbyTILDkNG5X/5UDpReIBD3VZfIrrXKX/groKbE +uiH9vdHkhdbOV1WkINuz+12Hdfk7irRXPRNC6SQVNeCy/DuCIEX+pQCAn60pc3eT +ctQG4oCiwQrlFMjoV9S5kbKoUavtuEt7Huo4YIVJK1/McEYq8mIM1W6MGOwXQI0b +rKsp1zRviiQWU5zijQYxepSpBNJcGS1lNhD1m5ycy7+0Zm7FqBa6nlf/2kLadREF +4o3bHljfrLTa+czV9lI9HjwpeLCfccx0T7etpv+u/JzSlt1MlAnlCNtz2wo1oNdi +scyRdRlb00AWQMneQfSYgwGHyQ8CAwEAAaMqMCgwDgYDVR0PAQH/BAQDAgeAMBYG +A1UdJQEB/wQMMAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQCc064W0uk3 +hVVYtHuOBPSag9TvyqJrnvHsPgWiwFTh7t4CGF2TiH6myxkboAN0BGZqIj0zorT+ +VORmZ4PrDqV29q8M77n4aTmDmqXXcCAMOtyC87xlK+YvsVtrvu2zYXnZV+BJ+UtT +FpDqgMLrE0ecnkDClAK4vPx3TqSzU3v//lgUG1o3VibJbzMptggMVA4Hl9AXGLnU +FNpK5B4mm/PQHQC1Ma/nweMoDcVlQUne8XgnwEf0ixGkViFLm6FmI7DfKUpq3zXb +vWKu8qiBmz4tju6LT2n+q66MNEMmS1qhuJJYZrORJgQkCVbo1RRwW6UNZSIjD8D6 +8QJhq7hCxteN +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAv1QcyGYCRsQm2DuPEBiNFvJMgsOQ0blf/lQOlF4gEPdVl8iu +tcpf+CugpsS6If290eSF1s5XVaQg27P7XYd1+TuKtFc9E0LpJBU14LL8O4IgRf6l +AICfrSlzd5Ny1AbigKLBCuUUyOhX1LmRsqhRq+24S3se6jhghUkrX8xwRiryYgzV +bowY7BdAjRusqynXNG+KJBZTnOKNBjF6lKkE0lwZLWU2EPWbnJzLv7RmbsWoFrqe +V//aQtp1EQXijdseWN+stNr5zNX2Uj0ePCl4sJ9xzHRPt62m/678nNKW3UyUCeUI +23PbCjWg12KxzJF1GVvTQBZAyd5B9JiDAYfJDwIDAQABAoIBACNozL7l6ivwp4PD +WhHPiWUiyLg2u3mlBjgKlHwvA15AeC3ULUllv+ctI9lZdV1PGa9bzM1ZeN5XtuES +aUYBCPtsYppHvvzumDleV49TcM0OoyxxGVaDd4nTrxQFTO4irA7EkFeU2Ajqvz6W +bXmUHzFjmIUXrzwH3Q0t4oIjUvAZNhNY63G3XZ264pNckvtuRArgn0r7e+trplII +qDYPwOLPhorwG6a0HIsSWbECA+NbzC5wBIr4CMfDRiHDQ5g4cGstpbBAUkAs2LSU +2QcGp3AIqOnzMDxLTMqKcKQ9YXOMqTpVoyll+jkgdHLCqHjo+O51/E5AsjBcabmi +4LpeVsECgYEA+7g2y8J54GWhNOpJ+RQ6IvoUuA9YmEe3byIglat5b+AWuy7Miq4u +VSiIjEqDf8Ci1LxHrkRCe4S/9VZSNJdfbv5I1LW3Wx4JRZ1JFR5Z9B0XI5SdkokM +O9DXIJHgxSzC9kCKgBpH5KxqMpEdMMv70C7gbMpnONEL1zIOZJxAwq8CgYEAwpUB +Dp5l8Wpma5SnUAJiTU9XdgtPr1M8WFde9jP3e2VK2O4DmnZkLN5aLbMfnftUNAl1 +mP4CTxtkkEwNtkol+rZAy6wwzQA/TP2yC0Wfw+xeDTKJ+JDDoWM+4FAhjBpns/gx +Ehfqj76jRjBW9DtARaHgrIHHFUn2p6wMZq4Sd6ECgYEA4jlNrdQrGnvb5KWHM750 +/UhJ5J2OHtWdStid9kU0j1ISu8k0dJJT+57BEWxKQD9NV+madkjMgxvsNL6OhMti +LmuD4v8pOU+GP7U6oCs15slaKVUARFi80OlA3fmcyzgOQ6f/kV+NKzu0+ZsnY9p/ +hjsK4VsKZ6qgfJd1DgDLxusCgYArXCDcLRfycA9ascmG3sEhESkgOO0M2LN9zBpx +KqtfZ/cB2CgdZ3xzMylNPbkx7yuYXPNDoHbLQgNq1EfJ80P7VlmiCUDmrcNtWKsw +L9emRSnALx7nsPqnIAKG4dRX8Bpj1E67BXFTjtu7bFI0Im/0FFqIlnLSn6TDQGeT +Cf87gQKBgCgW/kFaQAhP5Pdb7oOQcaF4/dq50QNDyQMFOPKWHY/5IrsIrDVI5V/D +o1npLPB+YE3baQqo58JX1UuO83F4zlwzS3Q4lS3dxg+gdvgzFHvQd/SV5IDhmLWL +L5Hj+B02+FAiz8zVGumbVykvPtzgTb0E+0rJKNO0/EgGqWsk/oC0 +-----END RSA PRIVATE KEY----- +""" + +TEST_SSH_KEY_DATA_UNLOCK = 'unlockme' diff --git a/awx/main/tests/fact/__init__.py b/awx/main/tests/fact/__init__.py deleted file mode 100644 index 234499d6e9..0000000000 --- a/awx/main/tests/fact/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright (c) 2015 Ansible, Inc. -# All Rights Reserved - -from __future__ import absolute_import - -from .fact_api import * # noqa diff --git a/awx/main/tests/jobs/base.py b/awx/main/tests/job_base.py similarity index 98% rename from awx/main/tests/jobs/base.py rename to awx/main/tests/job_base.py index dcb056abb7..5b7408d19d 100644 --- a/awx/main/tests/jobs/base.py +++ b/awx/main/tests/job_base.py @@ -128,7 +128,7 @@ class BaseJobTestMixin(BaseTestMixin): # He works with Randall self.user_billybob = self.make_user('billybob') self.org_ops.users.add(self.user_billybob) - + # Jim is the newest intern. He can login, but can't do anything quite yet # except make everyone else fresh coffee. self.user_jim = self.make_user('jim') @@ -256,9 +256,9 @@ class BaseJobTestMixin(BaseTestMixin): self.team_ops_testers.users.add(self.user_billybob) # Each user has his/her own set of credentials. - from awx.main.tests.tasks import (TEST_SSH_KEY_DATA, - TEST_SSH_KEY_DATA_LOCKED, - TEST_SSH_KEY_DATA_UNLOCK) + from awx.main.tests.data.ssh import (TEST_SSH_KEY_DATA, + TEST_SSH_KEY_DATA_LOCKED, + TEST_SSH_KEY_DATA_UNLOCK) self.cred_sue = self.user_sue.credentials.create( username='sue', password=TEST_SSH_KEY_DATA, @@ -429,7 +429,7 @@ class BaseJobTestMixin(BaseTestMixin): #self.permission1 = Permission.objects.create( # inventory = self.inventory, # project = self.project, - # team = self.team, + # team = self.team, # permission_type = PERM_INVENTORY_DEPLOY, # created_by = self.normal_django_user #) @@ -441,7 +441,7 @@ class BaseJobTestMixin(BaseTestMixin): # permission_type = PERM_INVENTORY_CHECK, # created_by = self.normal_django_user #) - + # Engineering has job templates to check/run the dev project onto # their own inventory. self.jt_eng_check = JobTemplate.objects.create( diff --git a/awx/main/tests/jobs/__init__.py b/awx/main/tests/jobs/__init__.py deleted file mode 100644 index 092826ccf0..0000000000 --- a/awx/main/tests/jobs/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2015 Ansible, Inc. -# All Rights Reserved - -from __future__ import absolute_import - -from .jobs_monolithic import * # noqa -from .job_launch import * # noqa -from .job_relaunch import * # noqa -from .survey_password import * # noqa -from .start_cancel import * # noqa -from .base import * # noqa diff --git a/awx/main/tests/old/README.md b/awx/main/tests/old/README.md new file mode 100644 index 0000000000..92582d890d --- /dev/null +++ b/awx/main/tests/old/README.md @@ -0,0 +1,7 @@ +Old Tests +========= +This are the old django.TestCase / unittest.TestCase tests for Tower. + +No new tests should be added to this folder. Overtime, we will be refactoring +tests out of this folder as py.test tests and into their respective functional +and unit folders. diff --git a/awx/main/tests/activity_stream.py b/awx/main/tests/old/activity_stream.py similarity index 100% rename from awx/main/tests/activity_stream.py rename to awx/main/tests/old/activity_stream.py diff --git a/awx/main/tests/ad_hoc.py b/awx/main/tests/old/ad_hoc.py similarity index 99% rename from awx/main/tests/ad_hoc.py rename to awx/main/tests/old/ad_hoc.py index 957cd7c084..41993f885b 100644 --- a/awx/main/tests/ad_hoc.py +++ b/awx/main/tests/old/ad_hoc.py @@ -19,7 +19,11 @@ from crum import impersonate from awx.main.utils import * # noqa from awx.main.models import * # noqa from awx.main.tests.base import BaseJobExecutionTest -from awx.main.tests.tasks import TEST_SSH_KEY_DATA, TEST_SSH_KEY_DATA_LOCKED, TEST_SSH_KEY_DATA_UNLOCK +from awx.main.tests.data.ssh import ( + TEST_SSH_KEY_DATA, + TEST_SSH_KEY_DATA_LOCKED, + TEST_SSH_KEY_DATA_UNLOCK, +) __all__ = ['RunAdHocCommandTest', 'AdHocCommandApiTest'] @@ -568,7 +572,7 @@ class AdHocCommandApiTest(BaseAdHocCommandTest): with self.current_user('admin'): response = self.run_test_ad_hoc_command(become_enabled=True) self.assertEqual(response['become_enabled'], True) - + # Try to run with expired license. self.create_expired_license_file() with self.current_user('admin'): @@ -1199,7 +1203,7 @@ class AdHocCommandApiTest(BaseAdHocCommandTest): with self.current_user('admin'): response = self.run_test_ad_hoc_command() - # Test the ad hoc command events list for a host. Should return the + # Test the ad hoc command events list for a host. Should return the # events only for that particular host. url = reverse('api:host_ad_hoc_command_events_list', args=(self.host.pk,)) with self.current_user('admin'): diff --git a/awx/main/tests/commands/age_deleted.py b/awx/main/tests/old/commands/age_deleted.py similarity index 95% rename from awx/main/tests/commands/age_deleted.py rename to awx/main/tests/old/commands/age_deleted.py index 02738c2c1f..ec5591d28e 100644 --- a/awx/main/tests/commands/age_deleted.py +++ b/awx/main/tests/old/commands/age_deleted.py @@ -3,7 +3,7 @@ # AWX from awx.main.tests.base import BaseTest -from awx.main.tests.commands.base import BaseCommandMixin +from command_base import BaseCommandMixin __all__ = ['AgeDeletedCommandFunctionalTest'] diff --git a/awx/main/tests/commands/cleanup_facts.py b/awx/main/tests/old/commands/cleanup_facts.py similarity index 99% rename from awx/main/tests/commands/cleanup_facts.py rename to awx/main/tests/old/commands/cleanup_facts.py index d6f0bd0b97..fc0f049aad 100644 --- a/awx/main/tests/commands/cleanup_facts.py +++ b/awx/main/tests/old/commands/cleanup_facts.py @@ -12,7 +12,7 @@ from django.core.management.base import CommandError # AWX from awx.main.tests.base import BaseTest from awx.fact.tests.base import MongoDBRequired, FactScanBuilder, TEST_FACT_PACKAGES, TEST_FACT_ANSIBLE, TEST_FACT_SERVICES -from awx.main.tests.commands.base import BaseCommandMixin +from command_base import BaseCommandMixin from awx.main.management.commands.cleanup_facts import Command, CleanupFacts from awx.fact.models.fact import * # noqa @@ -45,7 +45,7 @@ class CleanupFactsCommandFunctionalTest(BaseCommandMixin, BaseTest, MongoDBRequi def test_invoke_params_required(self): result, stdout, stderr = self.run_command('cleanup_facts') self.assertIsInstance(result, CommandError) - self.assertEqual(str(result), 'Both --granularity and --older_than are required.') + self.assertEqual(str(result), 'Both --granularity and --older_than are required.') def test_module(self): self.builder.add_fact('packages', TEST_FACT_PACKAGES) diff --git a/awx/main/tests/commands/base.py b/awx/main/tests/old/commands/command_base.py similarity index 100% rename from awx/main/tests/commands/base.py rename to awx/main/tests/old/commands/command_base.py diff --git a/awx/main/tests/commands/commands_monolithic.py b/awx/main/tests/old/commands/commands_monolithic.py similarity index 99% rename from awx/main/tests/commands/commands_monolithic.py rename to awx/main/tests/old/commands/commands_monolithic.py index d13bbe05f2..af4916e42d 100644 --- a/awx/main/tests/commands/commands_monolithic.py +++ b/awx/main/tests/old/commands/commands_monolithic.py @@ -471,7 +471,7 @@ class CleanupJobsTest(BaseCommandMixin, BaseLiveServerTest): self.assertTrue(ad_hoc_command.signal_start()) ad_hoc_command = AdHocCommand.objects.get(pk=ad_hoc_command.pk) self.assertEqual(ad_hoc_command.status, 'successful') - + # With days=1, no jobs will be deleted. jobs_before = Job.objects.all().count() self.assertTrue(jobs_before) @@ -690,7 +690,7 @@ class InventoryImportTest(BaseCommandMixin, BaseLiveServerTest): self.assertTrue('required' in str(result)) # Inventory ID, with invalid source. invalid_source = ''.join([os.path.splitext(self.ini_path)[0] + '-invalid', - os.path.splitext(self.ini_path)[1]]) + os.path.splitext(self.ini_path)[1]]) result, stdout, stderr = self.run_command('inventory_import', inventory_id=inventory_id, source=invalid_source) @@ -766,7 +766,7 @@ class InventoryImportTest(BaseCommandMixin, BaseLiveServerTest): self.assertEqual(group.children.count(), 0) hosts = set(group.hosts.values_list('name', flat=True)) host_names = set(['db1.example.com','db2.example.com']) - self.assertEqual(hosts, host_names) + self.assertEqual(hosts, host_names) elif group.name == 'webservers': self.assertEqual(group.variables_dict, {'webvar': 'blah'}) self.assertEqual(group.children.count(), 0) @@ -860,7 +860,7 @@ class InventoryImportTest(BaseCommandMixin, BaseLiveServerTest): self.assertEqual(group.children.filter(active=True).count(), 0) hosts = set(group.hosts.filter(active=True).values_list('name', flat=True)) host_names = set(['db1.example.com','db2.example.com']) - self.assertEqual(hosts, host_names) + self.assertEqual(hosts, host_names) elif group.name == 'webservers': self.assertEqual(group.variables_dict, {'webvar': 'blah'}) self.assertEqual(group.children.filter(active=True).count(), 0) @@ -1013,8 +1013,8 @@ class InventoryImportTest(BaseCommandMixin, BaseLiveServerTest): rest_api_url = urlparse.urlunsplit([parts.scheme, netloc, parts.path, parts.query, parts.fragment]) os.environ.setdefault('REST_API_URL', rest_api_url) - os.environ['INVENTORY_ID'] = str(old_inv.pk) - source = os.path.join(os.path.dirname(__file__), '..', '..', '..', 'plugins', + os.environ['INVENTORY_ID'] = str(old_inv.pk) + source = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'plugins', 'inventory', 'awxrest.py') result, stdout, stderr = self.run_command('inventory_import', inventory_id=new_inv.pk, @@ -1051,7 +1051,7 @@ class InventoryImportTest(BaseCommandMixin, BaseLiveServerTest): new_inv = self.organizations[0].inventories.create(name='newec2') self.assertEqual(new_inv.hosts.count(), 0) self.assertEqual(new_inv.groups.count(), 0) - os.chdir(os.path.join(os.path.dirname(__file__), '..', 'data')) + os.chdir(os.path.join(os.path.dirname(__file__), '..', '..', 'data')) inv_file = 'large_ec2_inventory.py' result, stdout, stderr = self.run_command('inventory_import', inventory_id=new_inv.pk, @@ -1072,7 +1072,7 @@ class InventoryImportTest(BaseCommandMixin, BaseLiveServerTest): new_inv = self.organizations[0].inventories.create(name='splunk') self.assertEqual(new_inv.hosts.count(), 0) self.assertEqual(new_inv.groups.count(), 0) - inv_file = os.path.join(os.path.dirname(__file__), '..', 'data', + inv_file = os.path.join(os.path.dirname(__file__), '..', '..', 'data', 'splunk_inventory.py') result, stdout, stderr = self.run_command('inventory_import', inventory_id=new_inv.pk, @@ -1095,7 +1095,7 @@ class InventoryImportTest(BaseCommandMixin, BaseLiveServerTest): def _check_largeinv_import(self, new_inv, nhosts, nhosts_inactive=0): self._start_time = time.time() - inv_file = os.path.join(os.path.dirname(__file__), '..', 'data', 'largeinv.py') + inv_file = os.path.join(os.path.dirname(__file__), '..', '..', 'data', 'largeinv.py') ngroups = self._get_ngroups_for_nhosts(nhosts) os.environ['NHOSTS'] = str(nhosts) result, stdout, stderr = self.run_command('inventory_import', diff --git a/awx/main/tests/commands/remove_instance.py b/awx/main/tests/old/commands/remove_instance.py similarity index 96% rename from awx/main/tests/commands/remove_instance.py rename to awx/main/tests/old/commands/remove_instance.py index d93285ea7e..6fa8d65d4b 100644 --- a/awx/main/tests/commands/remove_instance.py +++ b/awx/main/tests/old/commands/remove_instance.py @@ -6,7 +6,7 @@ import uuid # AWX from awx.main.tests.base import BaseTest -from awx.main.tests.commands.base import BaseCommandMixin +from command_base import BaseCommandMixin from awx.main.models import * # noqa __all__ = ['RemoveInstanceCommandFunctionalTest'] diff --git a/awx/main/tests/commands/run_fact_cache_receiver.py b/awx/main/tests/old/commands/run_fact_cache_receiver.py similarity index 99% rename from awx/main/tests/commands/run_fact_cache_receiver.py rename to awx/main/tests/old/commands/run_fact_cache_receiver.py index 0dac618758..7dedf7657a 100644 --- a/awx/main/tests/commands/run_fact_cache_receiver.py +++ b/awx/main/tests/old/commands/run_fact_cache_receiver.py @@ -12,7 +12,7 @@ from mock import MagicMock # AWX from awx.main.tests.base import BaseTest from awx.fact.tests.base import MongoDBRequired -from awx.main.tests.commands.base import BaseCommandMixin +from command_base import BaseCommandMixin from awx.main.management.commands.run_fact_cache_receiver import FactCacheReceiver from awx.fact.models.fact import * # noqa diff --git a/awx/main/tests/commands/run_socketio_service.py b/awx/main/tests/old/commands/run_socketio_service.py similarity index 100% rename from awx/main/tests/commands/run_socketio_service.py rename to awx/main/tests/old/commands/run_socketio_service.py diff --git a/awx/main/tests/commands/update_password.py b/awx/main/tests/old/commands/update_password.py similarity index 94% rename from awx/main/tests/commands/update_password.py rename to awx/main/tests/old/commands/update_password.py index 60eb04de88..cecbb1667d 100644 --- a/awx/main/tests/commands/update_password.py +++ b/awx/main/tests/old/commands/update_password.py @@ -3,7 +3,7 @@ # AWX from awx.main.tests.base import BaseTest -from awx.main.tests.commands.base import BaseCommandMixin +from command_base import BaseCommandMixin # Django from django.core.management.base import CommandError @@ -20,16 +20,16 @@ class UpdatePasswordCommandFunctionalTest(BaseCommandMixin, BaseTest): def test_updated_ok(self): result, stdout, stderr = self.run_command('update_password', username='admin', password='dingleberry') self.assertEqual(stdout, 'Password updated\n') - + def test_same_password(self): result, stdout, stderr = self.run_command('update_password', username='admin', password='admin') self.assertEqual(stdout, 'Password not updated\n') - + def test_error_username_required(self): result, stdout, stderr = self.run_command('update_password', password='foo') self.assertIsInstance(result, CommandError) self.assertEqual(str(result), 'username required') - + def test_error_password_required(self): result, stdout, stderr = self.run_command('update_password', username='admin') self.assertIsInstance(result, CommandError) diff --git a/awx/main/tests/fact/fact_api.py b/awx/main/tests/old/fact/fact_api.py similarity index 99% rename from awx/main/tests/fact/fact_api.py rename to awx/main/tests/old/fact/fact_api.py index 157cec3757..d13b17f060 100644 --- a/awx/main/tests/fact/fact_api.py +++ b/awx/main/tests/old/fact/fact_api.py @@ -181,7 +181,7 @@ class FactViewApiTest(FactApiBaseTest): def test_view_time_filter(self): self.setup_facts(6) ts = self.builder.get_timestamp(3) - self.get_fact(Fact.objects.filter(host=self.fact_host, module='ansible', timestamp__lte=ts).order_by('-timestamp')[0], + self.get_fact(Fact.objects.filter(host=self.fact_host, module='ansible', timestamp__lte=ts).order_by('-timestamp')[0], dict(datetime=ts)) diff --git a/awx/main/tests/ha.py b/awx/main/tests/old/ha.py similarity index 100% rename from awx/main/tests/ha.py rename to awx/main/tests/old/ha.py diff --git a/awx/main/tests/inventory.py b/awx/main/tests/old/inventory.py similarity index 99% rename from awx/main/tests/inventory.py rename to awx/main/tests/old/inventory.py index de7149df3e..9503b4232c 100644 --- a/awx/main/tests/inventory.py +++ b/awx/main/tests/old/inventory.py @@ -151,11 +151,11 @@ class InventoryTest(BaseTest): def test_put_inventory_detail(self): url_a = reverse('api:inventory_detail', args=(self.inventory_a.pk,)) url_b = reverse('api:inventory_detail', args=(self.inventory_b.pk,)) - + # Check put to detail view with invalid authentication. self.check_invalid_auth(url_a, methods=('put',)) self.check_invalid_auth(url_b, methods=('put',)) - + # a super user can update inventory records with self.current_user(self.super_django_user): data = self.get(url_a, expect=200) @@ -200,7 +200,7 @@ class InventoryTest(BaseTest): self.put(url_a, data, expect=403) # Via AC-376: - # Create an inventory. Leave the description empty. + # Create an inventory. Leave the description empty. # Edit the new inventory, change the Name, click Save. list_url = reverse('api:inventory_list') new_data = dict(name='inventory-c', description='', @@ -220,13 +220,13 @@ class InventoryTest(BaseTest): def test_delete_inventory_detail(self): url_a = reverse('api:inventory_detail', args=(self.inventory_a.pk,)) url_b = reverse('api:inventory_detail', args=(self.inventory_b.pk,)) - + # Create test hosts and groups within each inventory. self.inventory_a.hosts.create(name='host-a') self.inventory_a.groups.create(name='group-a') self.inventory_b.hosts.create(name='host-b') self.inventory_b.groups.create(name='group-b') - + # Check put to detail view with invalid authentication. self.check_invalid_auth(url_a, methods=('delete',)) self.check_invalid_auth(url_b, methods=('delete',)) @@ -487,7 +487,7 @@ class InventoryTest(BaseTest): self.post(url5, data=new_group_d, expect=400, auth=self.get_other_credentials()) got = self.get(url5, expect=200, auth=self.get_other_credentials()) self.assertEquals(got['count'], 5) - + # side check: see if root groups URL is operational. These are groups without parents. root_groups = self.get(root_groups, expect=200, auth=self.get_super_credentials()) self.assertEquals(root_groups['count'], 2) @@ -497,7 +497,7 @@ class InventoryTest(BaseTest): self.post(url5, data=remove_me, expect=204, auth=self.get_other_credentials()) got = self.get(url5, expect=200, auth=self.get_other_credentials()) self.assertEquals(got['count'], 4) - + ################################################### # VARIABLES @@ -507,31 +507,31 @@ class InventoryTest(BaseTest): # attempting to get a variable object creates it, even though it does not already exist vdata_url = reverse('api:host_variable_data', args=(added_by_collection_a['id'],)) - + got = self.get(vdata_url, expect=200, auth=self.get_super_credentials()) self.assertEquals(got, {}) # super user can create variable objects # an org admin can create variable objects (defers to inventory permissions) got = self.put(vdata_url, data=vars_a, expect=200, auth=self.get_super_credentials()) - self.assertEquals(got, vars_a) + self.assertEquals(got, vars_a) - # verify that we can update things and get them back + # verify that we can update things and get them back got = self.put(vdata_url, data=vars_c, expect=200, auth=self.get_super_credentials()) - self.assertEquals(got, vars_c) + self.assertEquals(got, vars_c) got = self.get(vdata_url, expect=200, auth=self.get_super_credentials()) - self.assertEquals(got, vars_c) + self.assertEquals(got, vars_c) # a normal user cannot edit variable objects self.put(vdata_url, data=vars_a, expect=403, auth=self.get_nobody_credentials()) # a normal user with inventory write permissions can edit variable objects... got = self.put(vdata_url, data=vars_b, expect=200, auth=self.get_normal_credentials()) - self.assertEquals(got, vars_b) + self.assertEquals(got, vars_b) ################################################### # VARIABLES -> GROUPS - + vars_a = dict(asdf=7777, dog='droopy', cat='battlecat', unstructured=dict(a=[1,1,1],b=dict(x=1,y=2))) vars_b = dict(asdf=8888, dog='snoopy', cat='cheshire', unstructured=dict(a=[2,2,2],b=dict(x=3,y=4))) vars_c = dict(asdf=9999, dog='pluto', cat='five', unstructured=dict(a=[3,3,3],b=dict(z=5))) @@ -547,7 +547,7 @@ class InventoryTest(BaseTest): # an org admin can associate variable objects with groups put = self.put(vdata1_url, data=vars_b, expect=200, auth=self.get_normal_credentials()) - + # a normal user cannot associate variable objects with groups put = self.put(vdata1_url, data=vars_b, expect=403, auth=self.get_nobody_credentials()) @@ -557,11 +557,11 @@ class InventoryTest(BaseTest): ################################################### # VARIABLES -> INVENTORY - + vars_a = dict(asdf=9873, dog='lassie', cat='heathcliff', unstructured=dict(a=[1,1,1],b=dict(x=1,y=2))) vars_b = dict(asdf=2736, dog='benji', cat='garfield', unstructured=dict(a=[2,2,2],b=dict(x=3,y=4))) vars_c = dict(asdf=7692, dog='buck', cat='sylvester', unstructured=dict(a=[3,3,3],b=dict(z=5))) - + vdata_url = reverse('api:inventory_variable_data', args=(self.inventory_a.pk,)) # a super user can associate variable objects with inventory @@ -700,7 +700,7 @@ class InventoryTest(BaseTest): new_data = dict(inventory=inv.pk, name='completely new', description='blarg?') kids = self.get(subgroups_url2, expect=200, auth=self.get_normal_credentials()) self.assertEqual(kids['count'], 1) - posted2 = self.post(subgroups_url2, data=new_data, expect=201, auth=self.get_normal_credentials()) + posted2 = self.post(subgroups_url2, data=new_data, expect=201, auth=self.get_normal_credentials()) # a group can't be it's own grandparent subsub = posted2['related']['children'] @@ -715,16 +715,16 @@ class InventoryTest(BaseTest): # double post causes conflict error (actually, should it? -- just got a 204, already associated) # self.post(subgroups_url2, data=got, expect=409, auth=self.get_normal_credentials()) - checked = self.get(subgroups_url2, expect=200, auth=self.get_normal_credentials()) + checked = self.get(subgroups_url2, expect=200, auth=self.get_normal_credentials()) # a normal user cannot set subgroups self.post(subgroups_url3, data=got, expect=403, auth=self.get_nobody_credentials()) # a normal user with inventory edit permissions can associate subgroups (but not when they belong to different inventories!) #self.post(subgroups_url3, data=got, expect=204, auth=self.get_other_credentials()) - #checked = self.get(subgroups_url3, expect=200, auth=self.get_normal_credentials()) + #checked = self.get(subgroups_url3, expect=200, auth=self.get_normal_credentials()) #self.assertEqual(checked['count'], 1) - + # slight detour # can see all hosts under a group, even if it has subgroups # this URL is NOT postable @@ -739,7 +739,7 @@ class InventoryTest(BaseTest): result = checked['results'][0] result['disassociate'] = 1 self.post(subgroups_url3, data=result, expect=204, auth=self.get_other_credentials()) - checked = self.get(subgroups_url3, expect=200, auth=self.get_normal_credentials()) + checked = self.get(subgroups_url3, expect=200, auth=self.get_normal_credentials()) self.assertEqual(checked['count'], 0) # try to double disassociate to see what happens (should no-op) self.post(subgroups_url3, data=result, expect=204, auth=self.get_other_credentials()) @@ -803,7 +803,7 @@ class InventoryTest(BaseTest): # FIXME: RELATED FIELDS # on an inventory resource, I can see related resources for hosts and groups and permissions - # and these work + # and these work # on a host resource, I can see related resources variables and inventories # and these work # on a group resource, I can see related resources for variables, inventories, and children @@ -884,11 +884,11 @@ class InventoryTest(BaseTest): g_d = self.inventory_a.groups.create(name='D') g_d.inventory_source g_d.parents.add(g_c) - + url = reverse('api:inventory_tree_view', args=(self.inventory_a.pk,)) with self.current_user(self.super_django_user): response = self.get(url, expect=200) - + self.assertTrue(isinstance(response, list)) self.assertEqual(len(response), 1) self.assertEqual(response[0]['id'], g_a.pk) diff --git a/awx/main/tests/jobs/job_launch.py b/awx/main/tests/old/jobs/job_launch.py similarity index 99% rename from awx/main/tests/jobs/job_launch.py rename to awx/main/tests/old/jobs/job_launch.py index 66a0ca5a72..4d1899de09 100644 --- a/awx/main/tests/jobs/job_launch.py +++ b/awx/main/tests/old/jobs/job_launch.py @@ -10,7 +10,7 @@ from django.core.urlresolvers import reverse # AWX from awx.main.models import * # noqa -from .base import BaseJobTestMixin +from awx.main.tests.job_base import BaseJobTestMixin import yaml __all__ = ['JobTemplateLaunchTest', 'JobTemplateLaunchPasswordsTest'] diff --git a/awx/main/tests/jobs/job_relaunch.py b/awx/main/tests/old/jobs/job_relaunch.py similarity index 98% rename from awx/main/tests/jobs/job_relaunch.py rename to awx/main/tests/old/jobs/job_relaunch.py index 04ae95ba75..437c6ed099 100644 --- a/awx/main/tests/jobs/job_relaunch.py +++ b/awx/main/tests/old/jobs/job_relaunch.py @@ -11,7 +11,7 @@ from django.core.urlresolvers import reverse # AWX from awx.main.models import * # noqa from awx.main.tests.base import BaseLiveServerTest -from .base import BaseJobTestMixin +from awx.main.tests.job_base import BaseJobTestMixin __all__ = ['JobRelaunchTest',] @@ -63,7 +63,7 @@ class JobRelaunchTest(BaseJobTestMixin, BaseLiveServerTest): self.jt_ops_east_run.extra_vars = jt_extra_vars self.jt_ops_east_run.save() - + response = self.post(url, {}, expect=201) j = Job.objects.get(pk=response['job']) self.assertTrue(j.status == 'successful') diff --git a/awx/main/tests/jobs/jobs_monolithic.py b/awx/main/tests/old/jobs/jobs_monolithic.py similarity index 99% rename from awx/main/tests/jobs/jobs_monolithic.py rename to awx/main/tests/old/jobs/jobs_monolithic.py index 7f3e337503..72283f29f9 100644 --- a/awx/main/tests/jobs/jobs_monolithic.py +++ b/awx/main/tests/old/jobs/jobs_monolithic.py @@ -22,7 +22,7 @@ import requests # AWX from awx.main.models import * # noqa -from base import BaseJobTestMixin +from awx.main.tests.job_base import BaseJobTestMixin __all__ = ['JobTemplateTest', 'JobTest', 'JobTemplateCallbackTest', 'JobTransactionTest', 'JobTemplateSurveyTest'] @@ -218,7 +218,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase): resp = self.get(url, expect=200) print [x['name'] for x in resp['results']] self.assertEquals(resp['count'], 3) - + # Chuck has permission to see all Eng Job Templates as Lead Engineer # Note: Since chuck is an org admin he can also see the support scan template with self.current_user(self.user_chuck): @@ -270,7 +270,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase): resp = self.get(url, expect=200) print [x['name'] for x in resp['results']] self.assertEquals(resp['count'], 6) - + def test_credentials_list(self): url = reverse('api:credential_list') @@ -331,7 +331,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase): d['job_type'] = 'world domination' response = self.post(url, d, expect=400) self.assertTrue('job_type' in response) - + # Test playbook not in list of project playbooks. with self.current_user(self.user_sue): d = dict(data.items()) @@ -603,11 +603,11 @@ class JobTest(BaseJobTestMixin, django.test.TestCase): data = self.get('/api/v1/job_templates/', expect=401) data = self.get('/api/v1/job_templates/', expect=200, auth=self.get_normal_credentials()) self.assertTrue(data['count'], 2) - + rec = dict( - name = 'job-foo', - credential = self.credential.pk, - inventory = self.inventory.pk, + name = 'job-foo', + credential = self.credential.pk, + inventory = self.inventory.pk, project = self.project.pk, job_type = PERM_INVENTORY_DEPLOY ) @@ -617,7 +617,7 @@ class JobTest(BaseJobTestMixin, django.test.TestCase): self.assertEquals(posted['url'], '/api/v1/job_templates/3/') # other_django_user is on a team that can deploy, so can create both deploy and check type jobs - rec['name'] = 'job-foo2' + rec['name'] = 'job-foo2' posted = self.post('/api/v1/job_templates/', rec, expect=201, auth=self.get_other_credentials()) rec['name'] = 'job-foo3' rec['job_type'] = PERM_INVENTORY_CHECK @@ -732,7 +732,7 @@ class JobTemplateCallbackTest(BaseJobTestMixin, django.test.LiveServerTestCase): raise socket.herror('unknown test host') raddr = '.'.join(list(reversed(ip.split('.'))) + ['in-addr', 'arpa']) return (host, [raddr], [ip]) - + def getaddrinfo(self, host, port, family=0, socktype=0, proto=0, flags=0): if family or socktype or proto or flags: return self._original_getaddrinfo(host, port, family, socktype, @@ -765,7 +765,7 @@ class JobTemplateCallbackTest(BaseJobTestMixin, django.test.LiveServerTestCase): host_vars['ansible_ssh_host'] = ip host.variables = json.dumps(host_vars) host.save() - + # Find a valid job template to use to test the callback. job_template = None qs = JobTemplate.objects.filter(job_type='run', @@ -1095,7 +1095,7 @@ class JobTemplateSurveyTest(BaseJobTestMixin, django.test.TestCase): jt_url = reverse('api:job_template_detail', args=(response['id'],)) with self.current_user(self.user_sue): self.patch(jt_url, dict(survey_enabled=True), expect=402) - + def test_post_job_template_survey(self): url = reverse('api:job_template_list') data = dict( @@ -1220,11 +1220,11 @@ class JobTemplateSurveyTest(BaseJobTestMixin, django.test.TestCase): self.get(url, expect=200) with self.current_user(self.user_chuck): - self.get(url, expect=200) + self.get(url, expect=200) # Doug and Juan can't with self.current_user(self.user_doug): self.get(url, expect=403) - + with self.current_user(self.user_juan): - self.get(url, expect=403) + self.get(url, expect=403) diff --git a/awx/main/tests/jobs/start_cancel.py b/awx/main/tests/old/jobs/start_cancel.py similarity index 98% rename from awx/main/tests/jobs/start_cancel.py rename to awx/main/tests/old/jobs/start_cancel.py index 54ff2255d9..e57c70ef15 100644 --- a/awx/main/tests/jobs/start_cancel.py +++ b/awx/main/tests/old/jobs/start_cancel.py @@ -11,7 +11,7 @@ from django.conf import settings # AWX from awx.main.models import * # noqa from awx.main.tests.base import BaseLiveServerTest -from .base import BaseJobTestMixin +from awx.main.tests.job_base import BaseJobTestMixin __all__ = ['JobStartCancelTest',] @@ -92,7 +92,7 @@ class JobStartCancelTest(BaseJobTestMixin, BaseLiveServerTest): # self.assertEqual(job.status, 'failed') # Test with a job that prompts for SSH unlock key, given the right key. - from awx.main.tests.tasks import TEST_SSH_KEY_DATA_UNLOCK + from awx.main.tests.data.ssh import TEST_SSH_KEY_DATA_UNLOCK # job = self.jt_ops_west_run.create_job( # credential=self.cred_greg, # created_by=self.user_sue, diff --git a/awx/main/tests/jobs/survey_password.py b/awx/main/tests/old/jobs/survey_password.py similarity index 99% rename from awx/main/tests/jobs/survey_password.py rename to awx/main/tests/old/jobs/survey_password.py index c5243712b5..f7588301d8 100644 --- a/awx/main/tests/jobs/survey_password.py +++ b/awx/main/tests/old/jobs/survey_password.py @@ -87,7 +87,7 @@ TEST_COMPLEX_SURVEY = ''' TEST_SINGLE_PASSWORDS = [ - { + { 'description': 'Single instance with a . after', 'text' : 'See spot. See spot run. See spot run %s. That is a fast run.' % PASSWORD, 'passwords': [PASSWORD], @@ -233,5 +233,5 @@ class SurveyPasswordRedactedTest(SurveyPasswordBaseTest): # should redact values in extra_vars def test_redact_job_extra_vars(self): for test in self.tests['simple']: - response = self._get_url_job_details(test['job']) + response = self._get_url_job_details(test['job']) self.check_extra_vars_redacted(test, response) diff --git a/awx/main/tests/licenses.py b/awx/main/tests/old/licenses.py similarity index 98% rename from awx/main/tests/licenses.py rename to awx/main/tests/old/licenses.py index 6703db54cd..d6cde2a0a4 100644 --- a/awx/main/tests/licenses.py +++ b/awx/main/tests/old/licenses.py @@ -46,7 +46,7 @@ class LicenseTests(BaseTest): def test_license_writer(self): - writer = TaskEngager( + writer = TaskEngager( company_name='acmecorp', contact_name='Michael DeHaan', contact_email='michael@ansibleworks.com', @@ -58,7 +58,7 @@ class LicenseTests(BaseTest): assert data['instance_count'] == 500 assert data['contact_name'] == 'Michael DeHaan' assert data['contact_email'] == 'michael@ansibleworks.com' - assert data['license_date'] == 25000 + assert data['license_date'] == 25000 assert data['license_key'] == "11bae31f31c6a6cdcb483a278cdbe98bd8ac5761acd7163a50090b0f098b3a13" strdata = writer.get_string() diff --git a/awx/main/tests/organizations.py b/awx/main/tests/old/organizations.py similarity index 99% rename from awx/main/tests/organizations.py rename to awx/main/tests/old/organizations.py index 8378ab12cb..cf3c64ab87 100644 --- a/awx/main/tests/organizations.py +++ b/awx/main/tests/old/organizations.py @@ -62,7 +62,7 @@ class OrganizationsTest(BaseTest): # TODO: Test non-enterprise license self.create_test_license_file() self.setup_users() - + self.organizations = self.make_organizations(self.super_django_user, 10) self.projects = self.make_projects(self.normal_django_user, 10) @@ -71,7 +71,7 @@ class OrganizationsTest(BaseTest): self.organizations[0].projects.add(project) for project in self.projects[3:8]: self.organizations[1].projects.add(project) - for project in self.projects[9:10]: + for project in self.projects[9:10]: self.organizations[2].projects.add(project) self.organizations[0].projects.add(self.projects[-1]) self.organizations[9].projects.add(self.projects[-2]) @@ -91,7 +91,7 @@ class OrganizationsTest(BaseTest): x.admins.add(self.super_django_user) x.users.add(self.super_django_user) x.users.add(self.other_django_user) - + self.organizations[0].users.add(self.normal_django_user) self.organizations[1].admins.add(self.normal_django_user) @@ -251,11 +251,11 @@ class OrganizationsTest(BaseTest): def test_post_item(self): new_org = dict(name='magic test org', description='8675309') - + # need to be a valid user self.post(self.collection(), new_org, expect=401, auth=None) self.post(self.collection(), new_org, expect=401, auth=self.get_invalid_credentials()) - + # only super users can create organizations self.post(self.collection(), new_org, expect=403, auth=self.get_normal_credentials()) self.post(self.collection(), new_org, expect=403, auth=self.get_other_credentials()) @@ -267,22 +267,22 @@ class OrganizationsTest(BaseTest): # look at what we got back from the post, make sure we added an org last_org = Organization.objects.order_by('-pk')[0] self.assertTrue(data1['url'].endswith("/%d/" % last_org.pk)) - + # Test that not even super users can create an organization with a basic license self.create_basic_license_file() cant_org = dict(name='silly user org', description='4815162342') self.post(self.collection(), cant_org, expect=402, auth=self.get_super_credentials()) def test_post_item_subobjects_projects(self): - + # first get all the orgs orgs = self.get(self.collection(), expect=200, auth=self.get_super_credentials()) - + # find projects attached to the first org projects0_url = orgs['results'][0]['related']['projects'] projects1_url = orgs['results'][1]['related']['projects'] projects2_url = orgs['results'][2]['related']['projects'] - + # get all the projects on the first org projects0 = self.get(projects0_url, expect=200, auth=self.get_super_credentials()) a_project = projects0['results'][-1] @@ -303,7 +303,7 @@ class OrganizationsTest(BaseTest): self.post(projects1_url, a_project, expect=204, auth=self.get_super_credentials()) projects1 = self.get(projects1_url, expect=200, auth=self.get_super_credentials()) self.assertEquals(projects1['count'], 5) - + a_project = projects1['results'][-1] a_project['disassociate'] = 1 projects1 = self.get(projects1_url, expect=200, auth=self.get_super_credentials()) @@ -324,7 +324,7 @@ class OrganizationsTest(BaseTest): # and can't do post a project he can read to an organization he cannot self.post(projects2_url, dict(id=new_project_a.pk), expect=403, auth=self.get_normal_credentials()) - + def test_post_item_subobjects_users(self): @@ -411,8 +411,8 @@ class OrganizationsTest(BaseTest): # any attempt to put a subobject should be a 405, edit the actual resource or POST with 'disassociate' to delete # this is against a collection URL anyway, so we really need not repeat this test for other object types - # as a PUT against a collection doesn't make much sense. - + # as a PUT against a collection doesn't make much sense. + orgs = self.get(self.collection(), expect=200, auth=self.get_super_credentials()) projects0_url = orgs['results'][0]['related']['projects'] sub_projects = self.get(projects0_url, expect=200, auth=self.get_super_credentials()) @@ -425,14 +425,14 @@ class OrganizationsTest(BaseTest): # first get some urls urls = self.get_urls(self.collection(), auth=self.get_super_credentials()) urldata1 = self.get(urls[1], auth=self.get_super_credentials()) - + # check authentication -- admins of the org and superusers can delete objects only self.delete(urls[0], expect=401, auth=None) self.delete(urls[0], expect=401, auth=self.get_invalid_credentials()) self.delete(urls[8], expect=403, auth=self.get_normal_credentials()) self.delete(urls[1], expect=204, auth=self.get_normal_credentials()) self.delete(urls[0], expect=204, auth=self.get_super_credentials()) - + # check that when we have deleted an object it comes back 404 via GET # but that it's still in the database as inactive self.get(urls[1], expect=404, auth=self.get_normal_credentials()) diff --git a/awx/main/tests/projects.py b/awx/main/tests/old/projects.py similarity index 99% rename from awx/main/tests/projects.py rename to awx/main/tests/old/projects.py index d12fd89e7b..b7378d14ef 100644 --- a/awx/main/tests/projects.py +++ b/awx/main/tests/old/projects.py @@ -21,7 +21,13 @@ from django.utils.timezone import now # AWX from awx.main.models import * # noqa from awx.main.tests.base import BaseTransactionTest -from awx.main.tests.tasks import TEST_SSH_KEY_DATA, TEST_SSH_KEY_DATA_LOCKED, TEST_SSH_KEY_DATA_UNLOCK, TEST_OPENSSH_KEY_DATA, TEST_OPENSSH_KEY_DATA_LOCKED +from awx.main.tests.data.ssh import ( + TEST_SSH_KEY_DATA, + TEST_SSH_KEY_DATA_LOCKED, + TEST_SSH_KEY_DATA_UNLOCK, + TEST_OPENSSH_KEY_DATA, + TEST_OPENSSH_KEY_DATA_LOCKED, +) from awx.main.utils import decrypt_field, update_scm_url TEST_PLAYBOOK = '''- hosts: mygroup @@ -238,7 +244,7 @@ class ProjectsTest(BaseTransactionTest): auth=self.get_super_credentials()) response = self.put(project_detail, project_data, expect=200, auth=self.get_super_credentials()) - + # cannot update using local_path from another project. project_data['local_path'] = self.projects[2].local_path response = self.put(project_detail, project_data, expect=400, @@ -391,14 +397,14 @@ class ProjectsTest(BaseTransactionTest): # ===================================================================== # TEAM PROJECTS - + team = Team.objects.filter(active=True, organization__pk=self.organizations[1].pk)[0] team_projects = reverse('api:team_projects_list', args=(team.pk,)) - + p1 = self.projects[0] team.projects.add(p1) team.save() - + got = self.get(team_projects, expect=200, auth=self.get_super_credentials()) # FIXME: project postablility tests somewhat incomplete. @@ -430,7 +436,7 @@ class ProjectsTest(BaseTransactionTest): self.post(team_users, data=dict(x, is_superuser=False), expect=204, auth=self.get_normal_credentials()) # The normal admin user can't create a super user vicariously through the team/project - self.post(team_users, data=dict(username='attempted_superuser_create', password='thepassword', + self.post(team_users, data=dict(username='attempted_superuser_create', password='thepassword', is_superuser=True), expect=403, auth=self.get_normal_credentials()) # ... but a superuser can self.post(team_users, data=dict(username='attempted_superuser_create', password='thepassword', @@ -682,7 +688,7 @@ class ProjectsTest(BaseTransactionTest): team = Team.objects.order_by('pk')[0] organization = Organization.objects.order_by('pk')[0] inventory = Inventory.objects.create( - name = 'test inventory', + name = 'test inventory', organization = organization, created_by = self.super_django_user ) @@ -691,10 +697,10 @@ class ProjectsTest(BaseTransactionTest): # can add permissions to a user user_permission = dict( - name='user can deploy a certain project to a certain inventory', + name='user can deploy a certain project to a certain inventory', # user=user.pk, # no need to specify, this will be automatically filled in - inventory=inventory.pk, - project=project.pk, + inventory=inventory.pk, + project=project.pk, permission_type=PERM_INVENTORY_DEPLOY ) team_permission = dict( @@ -993,7 +999,7 @@ class ProjectUpdatesTest(BaseTransactionTest): new_url = new_url or url new_url_u = new_url_u or url new_url_up = new_url_up or url - + # Check existing URL as-is. if is_exception(new_url): self.assertRaises(new_url, update_scm_url, scm_type, url) @@ -1130,7 +1136,7 @@ class ProjectUpdatesTest(BaseTransactionTest): after = file(path, 'rb').read() return path, before, after self.fail('no file found to change!') - + def check_project_scm(self, project): project = Project.objects.get(pk=project.pk) project_path = project.get_project_path(check_if_exists=False) diff --git a/awx/main/tests/redact.py b/awx/main/tests/old/redact.py similarity index 96% rename from awx/main/tests/redact.py rename to awx/main/tests/old/redact.py index ea61aebd77..3ce38bc7ad 100644 --- a/awx/main/tests/redact.py +++ b/awx/main/tests/old/redact.py @@ -38,15 +38,15 @@ uri = URI(scheme="https", username="myusername", password="mypasswordwith%40", h TEST_CLEARTEXT.append({ 'uri' : uri, 'text' : textwrap.dedent("""\ - PLAY [all] ******************************************************************** + PLAY [all] ******************************************************************** - TASK: [delete project directory before update] ******************************** + TASK: [delete project directory before update] ******************************** skipping: [localhost] - TASK: [update project using git and accept hostkey] *************************** + TASK: [update project using git and accept hostkey] *************************** skipping: [localhost] - TASK: [update project using git] ********************************************** + TASK: [update project using git] ********************************************** failed: [localhost] => {"cmd": "/usr/bin/git ls-remote https://%s:%s -h refs/heads/HEAD", "failed": true, "rc": 128} stderr: fatal: unable to access '%s': Could not resolve host: nonexistant.ansible.com @@ -54,10 +54,10 @@ TEST_CLEARTEXT.append({ FATAL: all hosts have already failed -- aborting - PLAY RECAP ******************************************************************** + PLAY RECAP ******************************************************************** to retry, use: --limit @/root/project_update.retry - localhost : ok=0 changed=0 unreachable=0 failed=1 + localhost : ok=0 changed=0 unreachable=0 failed=1 """ % (uri.username, uri.password, str(uri), str(uri))), 'host_occurrences' : 2 @@ -69,11 +69,11 @@ TEST_CLEARTEXT.append({ 'text' : textwrap.dedent("""\ TASK: [update project using git] ** failed: [localhost] => {"cmd": "/usr/bin/git ls-remote https://REDACTED:********", "failed": true, "rc": 128} - stderr: error: Couldn't resolve host '@%s' while accessing %s + stderr: error: Couldn't resolve host '@%s' while accessing %s fatal: HTTP request failed - msg: error: Couldn't resolve host '@%s' while accessing %s + msg: error: Couldn't resolve host '@%s' while accessing %s fatal: HTTP request failed """ % (uri.host, str(uri), uri.host, str(uri))), diff --git a/awx/main/tests/schedules.py b/awx/main/tests/old/schedules.py similarity index 100% rename from awx/main/tests/schedules.py rename to awx/main/tests/old/schedules.py diff --git a/awx/main/tests/scripts.py b/awx/main/tests/old/scripts.py similarity index 99% rename from awx/main/tests/scripts.py rename to awx/main/tests/old/scripts.py index 459070a868..cdf6758921 100644 --- a/awx/main/tests/scripts.py +++ b/awx/main/tests/old/scripts.py @@ -93,7 +93,7 @@ class InventoryScriptTest(BaseScriptTest): # add localhost just to make sure it's thrown into all (Ansible github bug) local = inventory.hosts.create(name='localhost', inventory=inventory, variables={}) - hosts.append(local) + hosts.append(local) self.hosts.extend(hosts) groups = [] @@ -130,7 +130,7 @@ class InventoryScriptTest(BaseScriptTest): os.environ.setdefault('REST_API_URL', rest_api_url) #os.environ.setdefault('REST_API_TOKEN', # self.super_django_user.auth_token.key) - name = os.path.join(os.path.dirname(__file__), '..', '..', 'plugins', + name = os.path.join(os.path.dirname(__file__), '..', '..', '..', 'plugins', 'inventory', 'awxrest.py') return self.run_script(name, *args, **options) diff --git a/awx/main/tests/settings.py b/awx/main/tests/old/settings.py similarity index 100% rename from awx/main/tests/settings.py rename to awx/main/tests/old/settings.py diff --git a/awx/main/tests/tasks.py b/awx/main/tests/old/tasks.py similarity index 84% rename from awx/main/tests/tasks.py rename to awx/main/tests/old/tasks.py index acdff99e29..a57202a958 100644 --- a/awx/main/tests/tasks.py +++ b/awx/main/tests/old/tasks.py @@ -22,6 +22,13 @@ from crum import impersonate from awx.main.utils import * # noqa from awx.main.models import * # noqa from awx.main.tests.base import BaseJobExecutionTest +from awx.main.tests.data.ssh import ( + TEST_SSH_KEY_DATA, + TEST_SSH_KEY_DATA_LOCKED, + TEST_OPENSSH_KEY_DATA, + TEST_SSH_CERT_KEY, + TEST_SSH_KEY_DATA_UNLOCK, +) TEST_PLAYBOOK = u''' - name: test success @@ -230,176 +237,6 @@ TEST_VAULT_PLAYBOOK = '''$ANSIBLE_VAULT;1.1;AES256 TEST_VAULT_PASSWORD = '1234' -TEST_SSH_KEY_DATA = '''-----BEGIN RSA PRIVATE KEY----- -MIIEpQIBAAKCAQEAyQ8F5bbgjHvk4SZJsKI9OmJKMFxZqRhvx4LaqjLTKbBwRBsY -1/C00NPiZn70dKbeyV7RNVZxuzM6yd3D3lwTdbDu/eJ0x72t3ch+TdLt/aenyy10 -IvZyhSlxCLDkDaVVPFYJOQzVS8TkdOi6ZHc+R0c0A+4ZE8OQ8C0zIKtUTHqRk4/v -gYK5guhNS0DdgWkBj6K+r/9D4bqdPTJPt4S7H75vb1tBgseiqftEkLYOhTK2gsCi -5uJgpG4zPQY4Kk/97dbW7pwcvPkr1rKkAwEJ27Bfo+DBv3oEx3SinpXQtOrH1aEO -RHSXldBaymdBtVLUhjxDlnnQ7Ps+fNX04R7N4QIDAQABAoIBAQClEDxbNyRqsVxa -q8BbzxZNVFxsD6Vceb9rIDa8/DT4SO4iO8zNm8QWnZ2FYDz5d/X3hGxlSa7dbVWa -XQJtD1K6kKPks4IEaejP58Ypxj20vWu4Fnz+Jy4lvLwb0n2n5lBv1IKF389NATw9 -7sL3sB3lDsPZZiQYYbogNDuBWqc+kP0zD84bONsM/B2HMRm9BRv2UsZf+zKU4pTA -UqHffyjmw7LqHmbtVjwVcUsC+xcE4kCuWLvabFnTWOSnWECyIw2+trxKdwCXbfzG -s5rn4Dj+aEKimzFaRpTSVx6w4yw9xw/EjsSaZ88jKSpTP8ocCut6zv+P/JwlukEX -4A4FxqyxAoGBAOp3G9EIAAWijcIgO5OdiZNEqVyqd3yyPzT6d/q7bf4dpVCZiLNA -bRmge83aMc4g2Dpkn/++It3bDmnXXGg+BZSX5KT9JLklXchaw9phv9J0diZEUvYS -mSQafbUGIqYnYzns3TU0cbgITs1iVIEstHYjGr3J88nDG+HFCHboxa93AoGBANuG -cDFgyvm79+haK2fHhUCZgaFFYBpkpuz+zjDjzIytOzymWa2gD9jIa7mvdvoH2ge3 -AVG0vy+n9cJaqJMuLkhdI01wVlqY9wvDHFyZCXyIvKVPMljKeTvCNGCupsG4R171 -gSKT5ryOx58MGbE7knAZC+QWpwxFpdpbfej6g7NnAoGBAMz6ipAJbXN/tG0FnvAj -pxXfzizcPw/+CTI40tGaMMQbiN5ZC+CiL39bBUFnQ2mQ31jVheegg3zvuL8hb4EW -z+wjitoPEZ7nowC5EUaHdJr6BBzaWKkWg1nD6yhqj7ow7xfCE3YjPlQEt1fpYjV4 -LuClOgi4WPCIKYUMq6TBRaprAoGAVrEjs0xPPApQH5EkXQp9BALbH23/Qs0G4sbJ -dKMxT0jGAPCMr7VrLKgRarXxXVImdy99NOAVNGO2+PbGZcEyA9/MJjO71nFb9mgp -1iOVjHmPThUVg90JvWC3QIsYTZ5RiR2Yzqfr0gDsslGb/9LPxLcPbBbKB12l3rKM -6amswvcCgYEAvgcSlTfAkI3ac8rB70HuDmSdqKblIiQjtPtT/ixXaFkZOmHRr4AE -KepMRDnaO/ldPDPEWCGqPzEM0t/0jS8/hCu3zLHHpZ+0LnHq+EXkOI0/GB4P+z5l -Vz3kouC0BTav0rCEnDop/cWMTiAp/XhKXfrTTTOra/F8l2xD8n/mnzY= ------END RSA PRIVATE KEY-----''' - -TEST_SSH_KEY_DATA_LOCKED = '''-----BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: AES-128-CBC,6B4E92AF4C29DE26FD8535D81825BDE6 - -pg8YplxPpfzgEGUiko34DGaYklyGyYKXjOrGFGyLoquNAVNFyewT34dDrZi0IAaE -79wMVcdlHbrJfZz8ML8I/ft6zM6BdlwZExH4y9DRAaktY3yIXxSvowBQ6ljh3wUy -M6m0afOfVjT22V8hLFgX0yTQ6P9zTG1cmj6+JQWTsMJ5EP3rnFK5CyrJXP48B3GI -GgE66rkXDvcKlVeIrbrpcTyfmEpafPgVRJYCDFXxeO/BfKgUFVxFq1PgFbvGQMmD -wA6EsyRrN+aoub1sqzj8tM8e4nwEi0EifdRShkFeqH4GUOKypanTXfCqwFBgYi5a -i3YwSnniZZPwCniGR5cl8oetrc5dubq/IR0txsGi2lO6zJEWdSer/EadS0QAll4S -yXrSc/lFaez1VmVe/8aoBKDOHhe7jV3YXAuqCeB4o/SThB/9Gad44MTbqFH3d7cD -k+F0Cjup7LZqZpXeB7ZHRG/Yt9MtBzwDVmEWaxA1WIN5a8xyZEVzRswSi4lZX69z -Va7eTKcrCbHOQmIbLZGRiZbAbfgriwwxQCJWELv80h+A754Bhi23n3WzcT094fRi -cqK//HcHHXxYGmrfUbHYcj+GCQ07Uk2ZR3qglmPISUCgfZwM9k0LpXudWE8vmF2S -pAnbgxgrfUMtpu5EAO+d8Sn5wQLVD7YzPBUhM4PYfYUbJnRoZQryuR4lqCzcg0te -BM8x1LzSXyBEbQaonuMzSz1hCQ9hZpUwUEqDWAT3cPNmgyWkXQ1P8ehJhTmryGJw -/GHxNzMZDGj+bBKo7ic3r1g3ZmmlSU1EVxMLvRBKhdc1XicBVqepDma6/LEpj+5X -oplR+3Q0QSQ8CchcSxYtOpI3UBCatpyu09GtfzS+7bI5I7FVYUccR83+oQlKpPHC -5O2irB8JeXqAY679fx2N4i0E6l5Xr5AjUtOBCNil0Y70eOf9ER6i7kGakR7bUtk5 -fQn8Em9pLsYYalnekn4sxyHpGq59KgNPjQiJRByYidSJ/oyNbmtPlxfXLwpuicd2 -8HLm1e0UeGidfF/bSlySwDzy1ZlSr/Apdcn9ou5hfhaGuQvjr9SvJwxQFNRMPdHj -ukBSDGuxyyU+qBrWJhFsymiZAWDofY/4GzgMu4hh0PwN5arzoTxnLHmc/VFttyMx -nP7bTaa9Sr54TlMr7NuKTzz5biXKjqJ9AZKIUF2+ERebjV0hMpJ5NPsLwPUnA9kx -R3tl1JL2Ia82ovS81Ghff/cBZsx/+LQYa+ac4eDTyXxyg4ei5tPwOlzz7pDKJAr9 -XEh2X6rywCNghEMZPaOQLiEDLJ2is6P4OarSa/yoU4OMetpFfwZ0oJSCmGlEa+CF -zeJ80yXhU1Ru2eqiUjCAUg25BFPwoiMJDc6jWWow7OrXCQsw7Ddo2ncy1p9QeWjM -2R4ojPHWuXKYxvwVSc8NZHASlycBCaxHLDAEyH4avOSDPWOB1H5t+RrNmo0qgush -0aRo6F7BjzB2rA4E+xu2u11TBfF8iB3PC919/vxnkXF97NqezsaCz6VbRlsU0A+B -wwoi+P4JlJF6ZuhuDv6mhmBCSdXdc1bvimvdpOljhThr+cG5mM08iqWGKdA665cw ------END RSA PRIVATE KEY----- -''' - -TEST_OPENSSH_KEY_DATA = '''-----BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn -NhAAAAAwEAAQAAAQEA1AZAwUJUiLmOXjbO5q2ZE5DF+gMpPKe8NEr12FpvOaJr1Nz/DNpf -FE/VbssOJ4CRD/6MItlPSG2pC1Cv3AYSL7NBc0YCMlBR/P/nLI8pLAzU3p3KRYvR+R6cMW -3nMcxyB1UUgzXY9dTVFIyejOsm7stGuNfdDTTLBE2vTDz6CyzxxSALEOdYut5cfeTUuG7d -nP01K3JiaHjHaXDmwraRR/JlitylaZUnSZ+/b9WCMX5FyeJ6CnGdvcCuvMK0iNjZ8R+PxP -xJBM5AlJC5J6qa8YmeaQ6lA/2S+/wGuhJmocmiXiLFy9IzIPnQiR+h8DqStp4xp245UQxe -TIGSMmq8DQAAA9A4FMRSOBTEUgAAAAdzc2gtcnNhAAABAQDUBkDBQlSIuY5eNs7mrZkTkM -X6Ayk8p7w0SvXYWm85omvU3P8M2l8UT9Vuyw4ngJEP/owi2U9IbakLUK/cBhIvs0FzRgIy -UFH8/+csjyksDNTencpFi9H5HpwxbecxzHIHVRSDNdj11NUUjJ6M6ybuy0a4190NNMsETa -9MPPoLLPHFIAsQ51i63lx95NS4bt2c/TUrcmJoeMdpcObCtpFH8mWK3KVplSdJn79v1YIx -fkXJ4noKcZ29wK68wrSI2NnxH4/E/EkEzkCUkLknqprxiZ5pDqUD/ZL7/Aa6EmahyaJeIs -XL0jMg+dCJH6HwOpK2njGnbjlRDF5MgZIyarwNAAAAAwEAAQAAAQAp8orBMYRUAJIgJavN -i67rZgslKZbw/yaHGgWFpm628mFvHcIAIvwIorrRTq8gNZl9lpjXFDNRWxDEwlPorfLPKS -Hb0pAAsE9oRKDR+gjlRCyhVop8M+t45At25A2HlrFArh5+zxp7mH4HsMJ1ktiDCgiV7W84 -e6dm1I/H/5BgwUlTNoVOGPrU183gqRsHIICjfmnjl2ObJoly+MTrAy7E9rSmsO+pHKl8z0 -XODWh3mo+EkCoYrK6kP96Jy3BepSmbZMROEsctS7Mkzu6QdnfTY3QqIzENYtTGJuAGktGj -su4MHP8hbj+TznNkFeZdmIC0uTnIKu1uquwuFF1HPZiBAAAAgACX9xPKS2J04WXpQag+JS -06n2zSuBHW7Kq4q/LMydoTRd8Quf6u6eivSBrl7H779LCtGCIZqJAslvWOyPyz2CohcCBU -emubiHcUA+aN7R9E0tyitwWraJjMIwpQ7+AbgdsLsuxozNeccSrr0tva2c5y9x7YGBcIdC -UJDt4xnBi7AAAAgQDz771v8Mb18kq5W+inDcYPFUNXGtNfeYZEOhYFpxunFnYwTEAG0Xnh -YpQXOAFZ2q5mkFQHMl4cOKwoAlaP0dM4v0JKPjFDLvGisEu95fnivj4YAMP/UHgKKxBbqW -HPUhg3adAmIJ9z9u/VmTErbVklcKWlyZuTUkxeQ/BJmSIRUQAAAIEA3oKAzdDURjy8zxLX -gBLCPdi8AxCiqQJBCsGxXCgKtZewset1XJHIN9ryfb4QSZFkSOlm/LgdeGtS8Or0GNPRYd -hgnUCF0LkEsDQ7HzPZYujLrAwjumvGQH6ORp5vRh0tQb93o4e1/A2vpdSKeH7gCe/jfUSY -h7dFGNoAI4cF7/0AAAAUcm9vdEBwaWxsb3cuaXhtbS5uZXQBAgMEBQYH ------END OPENSSH PRIVATE KEY----- -''' - -TEST_OPENSSH_KEY_DATA_LOCKED = '''-----BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABALaWMfjc -hSvC7aXxQs1ZDiAAAAEAAAAAEAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQDEDWKwZD8+ -h+2gZZKna8dy2QL4jJxM1eLGDcQDnuip1ixhaf5MT5T6BMploXXHs1pfuwx8yTQ6Ts/VJp -WX6cuHQg8sPGM3P7HNGUqs9q/EQfrrRxz555uL08CRaS6FjM/6x9iolNhHU910Wlg+R+ZS -xiMrrY/s03EiEChsAWTbwBGqTopGC2xMFgIxINoQtTFXv7MtCbDfl8aWKQRDmzkLvwT07N -ycj2kqADqoukD/2bQvPrW6FIZPJPpAdeAe2SZbf/y92NgVz/glOdtjaJp3oqn1QHrOA9/k -XgXOjgVQUbzX7qyLWenxM138VsRKUJZeROaHt1MWApLrLtKQ36SrAAAD0A+PODJjfeKm3U -JknlSYD7fFh6bVZGwG6LnLMtobs0elOfj2+sdg+hOVqyrA0rPOHES5yGKslTc/wRkRQ95m -dBleAyTDIOQ90IqDxT3lsNQwpscsFKPYKGmaUvZLLk4aNY1GeANtByXwTsjetVqn8Uo59A -zu6phX8Aagn2h0qxQwBnDjlzsXf6g5H7UPZd/t1dYr1NfVP6KWJrg0jivAI8tzO2HcM9W2 -cyOaodBw/6TsJNKvDV714Z+apvrNDEufBUsovKjAna2BDVZIhTCg5mYm0Dks8JStQrG2S1 -Yk8EM3+fpo8uMoHVz1jbYC8UX12pwIU67MhUn24KBxqulCYaTMsrLFkNWk6vKgwib+sIa4 -i1Bij1Zd0rdJWypQqTc2Oj3bBSYM47AksMXcKVpuNnFLh4+eokpQzbtIYpRqhOTh1Fky7z -xkhTgWVvf/F19M9t1bz3Rm1/t5I75Ag9qfKWs06j+VVfXnDt5v5hYAEhoJjMzSjgKaqc5g -YndeWeUwO6Vijt4XpkB8+0R7Kptsh9L0UUsNIcRoGcqrM8IUVb3D8vPWppPlj9d6LB+FCo -Cy1JlscnpBb8AQy9QMvrJTHKOyjRcenVxILPiN8PypIC008jvqpDzKimAxM4IMuA7AWE6w -j5+CzfUhDAJGdl2qH/nVc7GFUtz8bVA/v9Zkawg2MLcafgGollbLcTbKwDFcenQuyHT+Hj -uDm2f0oV/EDKFqLijlV8vcLBNUZoxY/L62Vora1jlqnapq2Z/AM9NicoELYNe21ReJ5dxM -7Pk/QdSrZjQzxoHf8uBDpb7x/KyfnSdf8GmdGCxoJ5mcepwD4tROMFC104tN0STJpdGVSm -Q5ZG1JDN7F9iJCCAwyulWH/XxTzFYnQ84199cQeV/M9rXXgbXa8ApAung6X9j8y1fcw9Lw -wV1aP06bCNgM0U50PiZ54HXwzVt+Ghs06TEF4/ZQiIgNJxdw0HFxAJj8qHqUCHuSmvBgnN -qRW/uruItwpXLaL00EHu7rAFlBi1BnnetI+D12ls04mlyTUFFM5v520B5zPV+5If2hx91w -C6Oxl1Wsp3gPkK2yiuy8qcrvoEoJ25TeEhUGEAPWx2OuQJO/Lpq9aF/JJoqGwnBaXdCsi+ -5ig+ZMq5GKQtyydzyXImjlNEUH1w2prRDiGVEufANA5LSLCtqOLgDzXS62WUBjJBrQJVAM -YpWz1tiZQoyv1RT3Y0O0Vwe2Z5AK3fVM0I5jWdiLrIErtcR4ULa6T56QtA52DufhKzINTR -Vg9TtUBqfKIpRQikPSjm7vpY/Xnbc= ------END OPENSSH PRIVATE KEY----- -''' - -TEST_SSH_CERT_KEY = """-----BEGIN CERTIFICATE----- -MIIDNTCCAh2gAwIBAgIBATALBgkqhkiG9w0BAQswSTEWMBQGA1UEAwwNV2luZG93 -cyBBenVyZTELMAkGA1UEBhMCVVMxIjAgBgkqhkiG9w0BCQEWE2x1a2VAc25lZXJp -bmdlci5jb20wHhcNMTQwNzI4MTQzMjExWhcNMTUwNzI4MTQzMjExWjBJMRYwFAYD -VQQDDA1XaW5kb3dzIEF6dXJlMQswCQYDVQQGEwJVUzEiMCAGCSqGSIb3DQEJARYT -bHVrZUBzbmVlcmluZ2VyLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAL9UHMhmAkbEJtg7jxAYjRbyTILDkNG5X/5UDpReIBD3VZfIrrXKX/groKbE -uiH9vdHkhdbOV1WkINuz+12Hdfk7irRXPRNC6SQVNeCy/DuCIEX+pQCAn60pc3eT -ctQG4oCiwQrlFMjoV9S5kbKoUavtuEt7Huo4YIVJK1/McEYq8mIM1W6MGOwXQI0b -rKsp1zRviiQWU5zijQYxepSpBNJcGS1lNhD1m5ycy7+0Zm7FqBa6nlf/2kLadREF -4o3bHljfrLTa+czV9lI9HjwpeLCfccx0T7etpv+u/JzSlt1MlAnlCNtz2wo1oNdi -scyRdRlb00AWQMneQfSYgwGHyQ8CAwEAAaMqMCgwDgYDVR0PAQH/BAQDAgeAMBYG -A1UdJQEB/wQMMAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQCc064W0uk3 -hVVYtHuOBPSag9TvyqJrnvHsPgWiwFTh7t4CGF2TiH6myxkboAN0BGZqIj0zorT+ -VORmZ4PrDqV29q8M77n4aTmDmqXXcCAMOtyC87xlK+YvsVtrvu2zYXnZV+BJ+UtT -FpDqgMLrE0ecnkDClAK4vPx3TqSzU3v//lgUG1o3VibJbzMptggMVA4Hl9AXGLnU -FNpK5B4mm/PQHQC1Ma/nweMoDcVlQUne8XgnwEf0ixGkViFLm6FmI7DfKUpq3zXb -vWKu8qiBmz4tju6LT2n+q66MNEMmS1qhuJJYZrORJgQkCVbo1RRwW6UNZSIjD8D6 -8QJhq7hCxteN ------END CERTIFICATE----- ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAv1QcyGYCRsQm2DuPEBiNFvJMgsOQ0blf/lQOlF4gEPdVl8iu -tcpf+CugpsS6If290eSF1s5XVaQg27P7XYd1+TuKtFc9E0LpJBU14LL8O4IgRf6l -AICfrSlzd5Ny1AbigKLBCuUUyOhX1LmRsqhRq+24S3se6jhghUkrX8xwRiryYgzV -bowY7BdAjRusqynXNG+KJBZTnOKNBjF6lKkE0lwZLWU2EPWbnJzLv7RmbsWoFrqe -V//aQtp1EQXijdseWN+stNr5zNX2Uj0ePCl4sJ9xzHRPt62m/678nNKW3UyUCeUI -23PbCjWg12KxzJF1GVvTQBZAyd5B9JiDAYfJDwIDAQABAoIBACNozL7l6ivwp4PD -WhHPiWUiyLg2u3mlBjgKlHwvA15AeC3ULUllv+ctI9lZdV1PGa9bzM1ZeN5XtuES -aUYBCPtsYppHvvzumDleV49TcM0OoyxxGVaDd4nTrxQFTO4irA7EkFeU2Ajqvz6W -bXmUHzFjmIUXrzwH3Q0t4oIjUvAZNhNY63G3XZ264pNckvtuRArgn0r7e+trplII -qDYPwOLPhorwG6a0HIsSWbECA+NbzC5wBIr4CMfDRiHDQ5g4cGstpbBAUkAs2LSU -2QcGp3AIqOnzMDxLTMqKcKQ9YXOMqTpVoyll+jkgdHLCqHjo+O51/E5AsjBcabmi -4LpeVsECgYEA+7g2y8J54GWhNOpJ+RQ6IvoUuA9YmEe3byIglat5b+AWuy7Miq4u -VSiIjEqDf8Ci1LxHrkRCe4S/9VZSNJdfbv5I1LW3Wx4JRZ1JFR5Z9B0XI5SdkokM -O9DXIJHgxSzC9kCKgBpH5KxqMpEdMMv70C7gbMpnONEL1zIOZJxAwq8CgYEAwpUB -Dp5l8Wpma5SnUAJiTU9XdgtPr1M8WFde9jP3e2VK2O4DmnZkLN5aLbMfnftUNAl1 -mP4CTxtkkEwNtkol+rZAy6wwzQA/TP2yC0Wfw+xeDTKJ+JDDoWM+4FAhjBpns/gx -Ehfqj76jRjBW9DtARaHgrIHHFUn2p6wMZq4Sd6ECgYEA4jlNrdQrGnvb5KWHM750 -/UhJ5J2OHtWdStid9kU0j1ISu8k0dJJT+57BEWxKQD9NV+madkjMgxvsNL6OhMti -LmuD4v8pOU+GP7U6oCs15slaKVUARFi80OlA3fmcyzgOQ6f/kV+NKzu0+ZsnY9p/ -hjsK4VsKZ6qgfJd1DgDLxusCgYArXCDcLRfycA9ascmG3sEhESkgOO0M2LN9zBpx -KqtfZ/cB2CgdZ3xzMylNPbkx7yuYXPNDoHbLQgNq1EfJ80P7VlmiCUDmrcNtWKsw -L9emRSnALx7nsPqnIAKG4dRX8Bpj1E67BXFTjtu7bFI0Im/0FFqIlnLSn6TDQGeT -Cf87gQKBgCgW/kFaQAhP5Pdb7oOQcaF4/dq50QNDyQMFOPKWHY/5IrsIrDVI5V/D -o1npLPB+YE3baQqo58JX1UuO83F4zlwzS3Q4lS3dxg+gdvgzFHvQd/SV5IDhmLWL -L5Hj+B02+FAiz8zVGumbVykvPtzgTb0E+0rJKNO0/EgGqWsk/oC0 ------END RSA PRIVATE KEY----- -""" - -TEST_SSH_KEY_DATA_UNLOCK = 'unlockme' - class RunJobTest(BaseJobExecutionTest): ''' Test cases for RunJob celery task. @@ -1077,7 +914,7 @@ class RunJobTest(BaseJobExecutionTest): self.assertTrue('"--become-method"' in job.job_args) self.assertTrue('"--ask-become-pass"' in job.job_args) self.assertTrue('"--become"' in job.job_args) - + def test_unlocked_ssh_key(self): self.create_test_credential(ssh_key_data=TEST_SSH_KEY_DATA) self.create_test_project(TEST_PLAYBOOK) @@ -1395,7 +1232,7 @@ class RunJobTest(BaseJobExecutionTest): # Hide local settings path. settings.AWX_PROOT_HIDE_PATHS = [os.path.join(settings.BASE_DIR, 'settings')] # Create another project alongside the one we're using to verify it - # is hidden. + # is hidden. self.create_test_credential() self.create_test_project(TEST_PLAYBOOK) other_project_path = self.project.local_path diff --git a/awx/main/tests/unified_jobs.py b/awx/main/tests/old/unified_jobs.py similarity index 100% rename from awx/main/tests/unified_jobs.py rename to awx/main/tests/old/unified_jobs.py diff --git a/awx/main/tests/users.py b/awx/main/tests/old/users.py similarity index 99% rename from awx/main/tests/users.py rename to awx/main/tests/old/users.py index 78aca9da4b..91720212ff 100644 --- a/awx/main/tests/users.py +++ b/awx/main/tests/old/users.py @@ -61,7 +61,7 @@ class AuthTokenLimitTest(BaseTest): 'token': response['token'] } self.get(user_me_url, expect=200, auth=auth_token1) - + mock_get_request_hash.return_value = "session_2" response = self.post(auth_token_url, data, expect=200, auth=None) auth_token2 = { @@ -133,7 +133,7 @@ class AuthTokenProxyTest(BaseTest): remote_addr = '192.168.75.1' auth_token = self._request_auth_token(remote_addr) - + # Verify we can access our own user information, from the remote address specified via HTTP_X_FORWARDED_FOR client_kwargs = {'HTTP_X_FORWARDED_FOR': remote_addr} response = self._get_me(expect=200, auth=auth_token, remote_addr=remote_addr, client_kwargs=client_kwargs) @@ -183,7 +183,7 @@ class UsersTest(BaseTest): url = reverse('api:user_list') new_user = dict(username='blippy') self.post(url, expect=400, data=new_user, auth=self.get_super_credentials()) - + def test_only_super_user_or_org_admin_can_add_users(self): url = reverse('api:user_list') new_user = dict(username='blippy', password='hippy') @@ -269,7 +269,7 @@ class UsersTest(BaseTest): # auth method was used in the request. response_header = response.response.get('WWW-Authenticate', '') self.assertEqual(response_header.split()[0], 'Token') - + # Request a new auth token from the new remote address. data = dict(zip(('username', 'password'), self.get_normal_credentials())) response = self.post(auth_token_url, data, expect=200, auth=None, @@ -298,7 +298,7 @@ class UsersTest(BaseTest): response = self.get(user_me_url, expect=401) response_header = response.response.get('WWW-Authenticate', '') self.assertEqual(response_header.split()[0], 'Basic') - + # A request that attempts Basic auth should request Basic auth again. response = self.get(user_me_url, expect=401, auth=('invalid', 'password')) @@ -431,7 +431,7 @@ class UsersTest(BaseTest): self.get(url, expect=404, auth=self.get_super_credentials()) obj = User.objects.get(pk=user_pk) self.assertEquals(obj.is_active, False) - + def test_non_org_admin_user_cannot_delete_any_user_including_himself(self): url1 = reverse('api:user_detail', args=(self.super_django_user.pk,)) url2 = reverse('api:user_detail', args=(self.normal_django_user.pk,)) @@ -471,11 +471,11 @@ class UsersTest(BaseTest): url = reverse('api:user_organizations_list', args=(self.normal_django_user.pk,)) data = self.get(url, expect=200, auth=self.get_normal_credentials()) - self.assertEquals(data['count'], 1) + self.assertEquals(data['count'], 1) # also accessible via superuser data = self.get(url, expect=200, auth=self.get_super_credentials()) - self.assertEquals(data['count'], 1) - # and also by other user... + self.assertEquals(data['count'], 1) + # and also by other user... data = self.get(url, expect=200, auth=self.get_other_credentials()) # but not by nobody user data = self.get(url, expect=403, auth=self.get_nobody_credentials()) @@ -492,7 +492,7 @@ class UsersTest(BaseTest): data = self.get(url, expect=200, auth=self.get_other_credentials()) # but not by nobody user data = self.get(url, expect=403, auth=self.get_nobody_credentials()) - + # teams the user is on, should be 0 url = reverse('api:user_teams_list', args=(self.normal_django_user.pk,)) data = self.get(url, expect=200, auth=self.get_normal_credentials()) @@ -566,7 +566,7 @@ class UsersTest(BaseTest): qs = base_qs.filter(username__exact='normal') self.assertTrue(qs.count()) self.check_get_list(url, self.super_django_user, qs) - + # Filter by username with __iexact suffix. url = '%s?username__iexact=NORMAL' % base_url qs = base_qs.filter(username__iexact='NORMAL') @@ -707,7 +707,7 @@ class UsersTest(BaseTest): self.assertTrue(qs.count()) self.check_get_list(url, self.super_django_user, qs) - # Filter by is_staff (field not exposed via API). FIXME: Should + # Filter by is_staff (field not exposed via API). FIXME: Should # eventually not be allowed! url = '%s?is_staff=true' % base_url qs = base_qs.filter(is_staff=True) @@ -792,7 +792,7 @@ class UsersTest(BaseTest): qs = base_qs.filter(organizations__admins__username__startswith='norm') self.assertTrue(qs.count()) self.check_get_list(url, self.super_django_user, qs) - + # Filter by username with __in list. url = '%s?username__in=normal,admin' % base_url qs = base_qs.filter(username__in=('normal', 'admin')) diff --git a/awx/main/tests/views.py b/awx/main/tests/old/views.py similarity index 96% rename from awx/main/tests/views.py rename to awx/main/tests/old/views.py index 6903b1ebf8..4ccd6f64ec 100644 --- a/awx/main/tests/views.py +++ b/awx/main/tests/old/views.py @@ -2,8 +2,11 @@ from django.core.urlresolvers import reverse # Reuse Test code -from awx.main.tests.base import BaseLiveServerTest, QueueStartStopTestMixin -from awx.main.tests.base import URI +from awx.main.tests.base import ( + BaseLiveServerTest, + QueueStartStopTestMixin, + URI, +) from awx.main.models.projects import * # noqa __all__ = ['UnifiedJobStdoutRedactedTests'] @@ -31,7 +34,7 @@ class UnifiedJobStdoutRedactedTests(BaseLiveServerTest, QueueStartStopTestMixin) def setUp(self): super(UnifiedJobStdoutRedactedTests, self).setUp() self.setup_instances() - self.setup_users() + self.setup_users() self.test_cases = [] self.negative_test_cases = [] diff --git a/awx/main/utils.py b/awx/main/utils.py index 63b4a9441c..110df9a5fd 100644 --- a/awx/main/utils.py +++ b/awx/main/utils.py @@ -522,4 +522,3 @@ def timedelta_total_seconds(timedelta): timedelta.microseconds + 0.0 + (timedelta.seconds + timedelta.days * 24 * 3600) * 10 ** 6) / 10 ** 6 - diff --git a/awx/settings/local_settings.py.docker_compose b/awx/settings/local_settings.py.docker_compose index 905e26857f..794d3ce073 100644 --- a/awx/settings/local_settings.py.docker_compose +++ b/awx/settings/local_settings.py.docker_compose @@ -30,10 +30,17 @@ DATABASES = { } } +def is_testing(argv): + if "py.test" in argv[0] or "py/test.py" in argv[0]: + return True + elif argv[1] == "test": + return True + return False + # Use SQLite for unit tests instead of PostgreSQL. If the lines below are # commented out, Django will create the test_awx-dev database in PostgreSQL to # run unit tests. -if len(sys.argv) >= 2 and sys.argv[1] == 'test': +if len(sys.argv) >= 2 and is_testing(sys.argv): DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', diff --git a/awx/settings/local_settings.py.example b/awx/settings/local_settings.py.example index 2fb0c745fc..52648798fe 100644 --- a/awx/settings/local_settings.py.example +++ b/awx/settings/local_settings.py.example @@ -30,10 +30,17 @@ DATABASES = { } } +def is_testing(argv): + if "py.test" in argv[0] or "py/test.py" in argv[0]: + return True + elif argv[1] == "test": + return True + return False + # Use SQLite for unit tests instead of PostgreSQL. If the lines below are # commented out, Django will create the test_awx-dev database in PostgreSQL to # run unit tests. -if len(sys.argv) >= 2 and sys.argv[1] == 'test': +if len(sys.argv) >= 2 and is_testing(sys.argv): DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000000..a679c1bdc4 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,6 @@ +[pytest] +DJANGO_SETTINGS_MODULE = awx.settings.development +python_paths = awx/lib/site-packages +site_dirs = awx/lib/site-packages +python_files = *.py +addopts = --create-db diff --git a/requirements/requirements_dev.txt b/requirements/requirements_dev.txt index a2ff6cf11a..bd7d5f54c8 100644 --- a/requirements/requirements_dev.txt +++ b/requirements/requirements_dev.txt @@ -4,3 +4,7 @@ django-debug-toolbar==1.3.2 unittest2 pep8 flake8 +pytest +pytest-cov +pytest-django +pytest-pythonpath diff --git a/requirements/requirements_jenkins.txt b/requirements/requirements_jenkins.txt index 8ccdb6c3a1..7ea9c8642f 100644 --- a/requirements/requirements_jenkins.txt +++ b/requirements/requirements_jenkins.txt @@ -9,3 +9,7 @@ pylint flake8 distribute==0.7.3 unittest2 +pytest +pytest-cov +pytest-django +pytest-pythonpath diff --git a/tools/docker-compose/Dockerfile b/tools/docker-compose/Dockerfile index 32be28ca01..b4a25a78cc 100644 --- a/tools/docker-compose/Dockerfile +++ b/tools/docker-compose/Dockerfile @@ -12,6 +12,7 @@ RUN echo "deb http://repo.mongodb.org/apt/ubuntu "$(lsb_release -sc)"/mongodb-or RUN apt-get update RUN apt-get install -y openssh-server ansible mg vim tmux git mercurial subversion python-dev python-psycopg2 make postgresql-client libpq-dev nodejs python-psutil libxml2-dev libxslt-dev lib32z1-dev libsasl2-dev libldap2-dev libffi-dev libzmq-dev proot python-pip libxmlsec1-dev swig redis-server && rm -rf /var/lib/apt/lists/* RUN pip install flake8 +RUN pip install pytest pytest-pythonpath pytest-django pytest-cov RUN /usr/bin/ssh-keygen -q -t rsa -N "" -f /root/.ssh/id_rsa RUN mkdir -p /etc/tower RUN mkdir -p /data/db