mirror of
https://github.com/ansible/awx.git
synced 2026-01-09 23:12:08 -03:30
added pytest to requirements_dev
reworking test strucutre reworked pytest.ini, removed functional imports, updated req_dev remove unneeded __init__ files add testing checker to local_settings examples adding testing packages to system Python for docker
This commit is contained in:
parent
5d6ea242c0
commit
3d4580611e
6
Makefile
6
Makefile
@ -357,17 +357,17 @@ pylint: reports
|
|||||||
@(set -o pipefail && $@ | reports/$@.report)
|
@(set -o pipefail && $@ | reports/$@.report)
|
||||||
|
|
||||||
check: flake8 pep8 # pyflakes pylint
|
check: flake8 pep8 # pyflakes pylint
|
||||||
|
|
||||||
# Run all API unit tests.
|
# Run all API unit tests.
|
||||||
test:
|
test:
|
||||||
$(PYTHON) manage.py test -v2 awx.main.tests
|
$(PYTHON) -m py.test awx/main/tests
|
||||||
|
|
||||||
test_unit:
|
test_unit:
|
||||||
$(PYTHON) -m py.test awx/main/tests/unit
|
$(PYTHON) -m py.test awx/main/tests/unit
|
||||||
|
|
||||||
# Run all API unit tests with coverage enabled.
|
# Run all API unit tests with coverage enabled.
|
||||||
test_coverage:
|
test_coverage:
|
||||||
coverage run manage.py test -v2 awx.main.tests
|
$(PYTHON) -m py.test --cov=awx awx/main/tests
|
||||||
|
|
||||||
# Output test coverage as HTML (into htmlcov directory).
|
# Output test coverage as HTML (into htmlcov directory).
|
||||||
coverage_html:
|
coverage_html:
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
# Copyright (c) 2015 Ansible, Inc.
|
# Copyright (c) 2015 Ansible, Inc.
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
|
|
||||||
|
import base64
|
||||||
|
import re
|
||||||
|
|
||||||
# Django
|
# Django
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|||||||
@ -1,24 +0,0 @@
|
|||||||
# Copyright (c) 2015 Ansible, Inc.
|
|
||||||
# All Rights Reserved.
|
|
||||||
import logging
|
|
||||||
logging.disable(logging.CRITICAL)
|
|
||||||
|
|
||||||
from .organizations import * # noqa
|
|
||||||
from .users import * # noqa
|
|
||||||
from .inventory import * # noqa
|
|
||||||
from .projects import ProjectsTest, ProjectUpdatesTest # noqa
|
|
||||||
from .commands import * # noqa
|
|
||||||
from .scripts import * # noqa
|
|
||||||
from .tasks import RunJobTest # noqa
|
|
||||||
from .ad_hoc import * # noqa
|
|
||||||
from .licenses import LicenseTests # noqa
|
|
||||||
from .jobs import * # noqa
|
|
||||||
from .activity_stream import * # noqa
|
|
||||||
from .schedules import * # noqa
|
|
||||||
from .redact import * # noqa
|
|
||||||
from .views import * # noqa
|
|
||||||
from .commands import * # noqa
|
|
||||||
from .fact import * # noqa
|
|
||||||
from .unified_jobs import * # noqa
|
|
||||||
from .ha import * # noqa
|
|
||||||
from .settings import * # noqa
|
|
||||||
@ -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
|
|
||||||
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
# Copyright (c) 2015 Ansible, Inc.
|
|
||||||
# All Rights Reserved
|
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
from .fact_api import * # noqa
|
|
||||||
@ -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
|
|
||||||
@ -523,125 +523,3 @@ def timedelta_total_seconds(timedelta):
|
|||||||
timedelta.microseconds + 0.0 +
|
timedelta.microseconds + 0.0 +
|
||||||
(timedelta.seconds + timedelta.days * 24 * 3600) * 10 ** 6) / 10 ** 6
|
(timedelta.seconds + timedelta.days * 24 * 3600) * 10 ** 6) / 10 ** 6
|
||||||
|
|
||||||
def validate_ssh_private_key(data):
|
|
||||||
"""Validate that the given SSH private key or certificate is,
|
|
||||||
in fact, valid.
|
|
||||||
"""
|
|
||||||
# Map the X in BEGIN X PRIVATE KEY to the key type (ssh-keygen -t).
|
|
||||||
# Tower jobs using OPENSSH format private keys may still fail if the
|
|
||||||
# system SSH implementation lacks support for this format.
|
|
||||||
key_types = {
|
|
||||||
'RSA': 'rsa',
|
|
||||||
'DSA': 'dsa',
|
|
||||||
'EC': 'ecdsa',
|
|
||||||
'OPENSSH': 'ed25519',
|
|
||||||
'': 'rsa1',
|
|
||||||
}
|
|
||||||
# Key properties to return if valid.
|
|
||||||
key_data = {
|
|
||||||
'key_type': None, # Key type (from above mapping).
|
|
||||||
'key_seg': '', # Key segment (all text including begin/end).
|
|
||||||
'key_b64': '', # Key data as base64.
|
|
||||||
'key_bin': '', # Key data as binary.
|
|
||||||
'key_enc': None, # Boolean, whether key is encrypted.
|
|
||||||
'cert_seg': '', # Cert segment (all text including begin/end).
|
|
||||||
'cert_b64': '', # Cert data as base64.
|
|
||||||
'cert_bin': '', # Cert data as binary.
|
|
||||||
}
|
|
||||||
data = data.strip()
|
|
||||||
validation_error = ValidationError('Invalid private key')
|
|
||||||
|
|
||||||
# Sanity check: We may potentially receive a full PEM certificate,
|
|
||||||
# and we want to accept these.
|
|
||||||
cert_begin_re = r'(-{4,})\s*BEGIN\s+CERTIFICATE\s*(-{4,})'
|
|
||||||
cert_end_re = r'(-{4,})\s*END\s+CERTIFICATE\s*(-{4,})'
|
|
||||||
cert_begin_match = re.search(cert_begin_re, data)
|
|
||||||
cert_end_match = re.search(cert_end_re, data)
|
|
||||||
if cert_begin_match and not cert_end_match:
|
|
||||||
raise validation_error
|
|
||||||
elif not cert_begin_match and cert_end_match:
|
|
||||||
raise validation_error
|
|
||||||
elif cert_begin_match and cert_end_match:
|
|
||||||
cert_dashes = set([cert_begin_match.groups()[0], cert_begin_match.groups()[1],
|
|
||||||
cert_end_match.groups()[0], cert_end_match.groups()[1]])
|
|
||||||
if len(cert_dashes) != 1:
|
|
||||||
raise validation_error
|
|
||||||
key_data['cert_seg'] = data[cert_begin_match.start():cert_end_match.end()]
|
|
||||||
|
|
||||||
# Find the private key, and also ensure that it internally matches
|
|
||||||
# itself.
|
|
||||||
# Set up the valid private key header and footer.
|
|
||||||
begin_re = r'(-{4,})\s*BEGIN\s+([A-Z0-9]+)?\s*PRIVATE\sKEY\s*(-{4,})'
|
|
||||||
end_re = r'(-{4,})\s*END\s+([A-Z0-9]+)?\s*PRIVATE\sKEY\s*(-{4,})'
|
|
||||||
begin_match = re.search(begin_re, data)
|
|
||||||
end_match = re.search(end_re, data)
|
|
||||||
if not begin_match or not end_match:
|
|
||||||
raise validation_error
|
|
||||||
|
|
||||||
# Ensure that everything, such as dash counts and key type, lines up,
|
|
||||||
# and raise an error if it does not.
|
|
||||||
dashes = set([begin_match.groups()[0], begin_match.groups()[2],
|
|
||||||
end_match.groups()[0], end_match.groups()[2]])
|
|
||||||
if len(dashes) != 1:
|
|
||||||
raise validation_error
|
|
||||||
if begin_match.groups()[1] != end_match.groups()[1]:
|
|
||||||
raise validation_error
|
|
||||||
key_type = begin_match.groups()[1] or ''
|
|
||||||
try:
|
|
||||||
key_data['key_type'] = key_types[key_type]
|
|
||||||
except KeyError:
|
|
||||||
raise ValidationError('Invalid private key: unsupported type %s' % key_type)
|
|
||||||
|
|
||||||
# The private key data begins and ends with the private key.
|
|
||||||
key_data['key_seg'] = data[begin_match.start():end_match.end()]
|
|
||||||
|
|
||||||
# Establish that we are able to base64 decode the private key;
|
|
||||||
# if we can't, then it's not a valid key.
|
|
||||||
#
|
|
||||||
# If we got a certificate, validate that also, in the same way.
|
|
||||||
header_re = re.compile(r'^(.+?):\s*?(.+?)(\\??)$')
|
|
||||||
for segment_name in ('cert', 'key'):
|
|
||||||
segment_to_validate = key_data['%s_seg' % segment_name]
|
|
||||||
# If we have nothing; skip this one.
|
|
||||||
# We've already validated that we have a private key above,
|
|
||||||
# so we don't need to do it again.
|
|
||||||
if not segment_to_validate:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Ensure that this segment is valid base64 data.
|
|
||||||
base64_data = ''
|
|
||||||
line_continues = False
|
|
||||||
lines = segment_to_validate.splitlines()
|
|
||||||
for line in lines[1:-1]:
|
|
||||||
line = line.strip()
|
|
||||||
if not line:
|
|
||||||
continue
|
|
||||||
if line_continues:
|
|
||||||
line_continues = line.endswith('\\')
|
|
||||||
continue
|
|
||||||
line_match = header_re.match(line)
|
|
||||||
if line_match:
|
|
||||||
line_continues = line.endswith('\\')
|
|
||||||
continue
|
|
||||||
base64_data += line
|
|
||||||
try:
|
|
||||||
decoded_data = base64.b64decode(base64_data)
|
|
||||||
if not decoded_data:
|
|
||||||
raise validation_error
|
|
||||||
key_data['%s_b64' % segment_name] = base64_data
|
|
||||||
key_data['%s_bin' % segment_name] = decoded_data
|
|
||||||
except TypeError:
|
|
||||||
raise validation_error
|
|
||||||
|
|
||||||
# Determine if key is encrypted.
|
|
||||||
if key_data['key_type'] == 'ed25519':
|
|
||||||
# See https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L3218
|
|
||||||
# Decoded key data starts with magic string (null-terminated), four byte
|
|
||||||
# length field, followed by the ciphername -- if ciphername is anything
|
|
||||||
# other than 'none' the key is encrypted.
|
|
||||||
key_data['key_enc'] = not bool(key_data['key_bin'].startswith('openssh-key-v1\x00\x00\x00\x00\x04none'))
|
|
||||||
else:
|
|
||||||
key_data['key_enc'] = bool('ENCRYPTED' in key_data['key_seg'])
|
|
||||||
|
|
||||||
return key_data
|
|
||||||
|
|
||||||
|
|||||||
@ -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
|
# 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
|
# commented out, Django will create the test_awx-dev database in PostgreSQL to
|
||||||
# run unit tests.
|
# run unit tests.
|
||||||
if len(sys.argv) >= 2 and sys.argv[1] == 'test':
|
if len(sys.argv) >= 2 and is_testing(sys.argv):
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
|||||||
@ -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
|
# 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
|
# commented out, Django will create the test_awx-dev database in PostgreSQL to
|
||||||
# run unit tests.
|
# run unit tests.
|
||||||
if len(sys.argv) >= 2 and sys.argv[1] == 'test':
|
if len(sys.argv) >= 2 and is_testing(sys.argv):
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
|||||||
5
pytest.ini
Normal file
5
pytest.ini
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[pytest]
|
||||||
|
DJANGO_SETTINGS_MODULE = awx.settings.development
|
||||||
|
python_paths = awx/lib/site-packages
|
||||||
|
python_files = *.py
|
||||||
|
addopts = --create-db
|
||||||
@ -4,3 +4,7 @@ django-debug-toolbar==1.3.2
|
|||||||
unittest2
|
unittest2
|
||||||
pep8
|
pep8
|
||||||
flake8
|
flake8
|
||||||
|
pytest
|
||||||
|
pytest-cov
|
||||||
|
pytest-django
|
||||||
|
pytest-pythonpath
|
||||||
|
|||||||
@ -12,6 +12,10 @@ RUN echo "deb http://repo.mongodb.org/apt/ubuntu "$(lsb_release -sc)"/mongodb-or
|
|||||||
RUN apt-get update
|
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 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 flake8
|
||||||
|
RUN pip install pytest
|
||||||
|
RUN pip install pytest-pythonpath
|
||||||
|
RUN pip install pytest-django
|
||||||
|
RUN pip install pytest-cov
|
||||||
RUN /usr/bin/ssh-keygen -q -t rsa -N "" -f /root/.ssh/id_rsa
|
RUN /usr/bin/ssh-keygen -q -t rsa -N "" -f /root/.ssh/id_rsa
|
||||||
RUN mkdir -p /etc/tower
|
RUN mkdir -p /etc/tower
|
||||||
RUN mkdir -p /data/db
|
RUN mkdir -p /data/db
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user