mirror of
https://github.com/ansible/awx.git
synced 2026-05-14 21:07:39 -02:30
Initial working test for run_launch_job task.
This commit is contained in:
@@ -95,7 +95,7 @@ class Command(NoArgsCommand):
|
|||||||
self.get_host(inventory, host, indent=indent)
|
self.get_host(inventory, host, indent=indent)
|
||||||
else:
|
else:
|
||||||
raise CommandError('Either --list or --host must be specified')
|
raise CommandError('Either --list or --host must be specified')
|
||||||
except CommandError:
|
except CommandError, e:
|
||||||
# Always return an empty hash on stdout, even when an error occurs.
|
# Always return an empty hash on stdout, even when an error occurs.
|
||||||
self.stdout.write(json.dumps({}))
|
self.stdout.write(json.dumps({}))
|
||||||
raise
|
raise
|
||||||
@@ -103,15 +103,21 @@ class Command(NoArgsCommand):
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# FIXME: The DJANGO_SETTINGS_MODULE environment variable *should* already
|
# FIXME: The DJANGO_SETTINGS_MODULE environment variable *should* already
|
||||||
# be set if this script is called from a celery task.
|
# be set if this script is called from a celery task.
|
||||||
settings_module = os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'lib.settings')
|
settings_module_name = os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'lib.settings')
|
||||||
# FIXME: Not particularly fond of this sys.path hack, but it is needed
|
# FIXME: Not particularly fond of this sys.path hack, but it is needed
|
||||||
# when a celery task calls ansible-playbook and needs to execute this
|
# when a celery task calls ansible-playbook and needs to execute this
|
||||||
# script directly.
|
# script directly.
|
||||||
try:
|
try:
|
||||||
__import__(settings_module)
|
settings_parent_module = __import__(settings_module_name)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
top_dir = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..')
|
top_dir = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..')
|
||||||
sys.path.insert(0, os.path.abspath(top_dir))
|
sys.path.insert(0, os.path.abspath(top_dir))
|
||||||
|
settings_parent_module = __import__(settings_module_name)
|
||||||
|
settings_module = getattr(settings_parent_module, settings_module_name.split('.')[-1])
|
||||||
|
# Use the ACOM_TEST_DATABASE_NAME environment variable to specify the test
|
||||||
|
# database name when called from unit tests.
|
||||||
|
if os.environ.get('ACOM_TEST_DATABASE_NAME', None):
|
||||||
|
settings_module.DATABASES['default']['NAME'] = os.environ['ACOM_TEST_DATABASE_NAME']
|
||||||
from django.core.management import execute_from_command_line
|
from django.core.management import execute_from_command_line
|
||||||
argv = [sys.argv[0], 'acom_inventory'] + sys.argv[1:]
|
argv = [sys.argv[0], 'acom_inventory'] + sys.argv[1:]
|
||||||
execute_from_command_line(argv)
|
execute_from_command_line(argv)
|
||||||
|
|||||||
@@ -608,8 +608,11 @@ class LaunchJob(CommonModel):
|
|||||||
from lib.main.tasks import run_launch_job
|
from lib.main.tasks import run_launch_job
|
||||||
launch_job_status = self.launch_job_statuses.create(name='Launch Job Status %s' % now().isoformat())
|
launch_job_status = self.launch_job_statuses.create(name='Launch Job Status %s' % now().isoformat())
|
||||||
task_result = run_launch_job.delay(launch_job_status.pk)
|
task_result = run_launch_job.delay(launch_job_status.pk)
|
||||||
launch_job_status.celery_task = TaskMeta.objects.get(task_id=task_result.task_id)
|
try:
|
||||||
launch_job_status.save()
|
launch_job_status.celery_task = TaskMeta.objects.get(task_id=task_result.task_id)
|
||||||
|
launch_job_status.save()
|
||||||
|
except TaskMeta.DoesNotExist:
|
||||||
|
pass
|
||||||
return launch_job_status
|
return launch_job_status
|
||||||
|
|
||||||
# project has one default playbook but really should have a list of playbooks and flags ...
|
# project has one default playbook but really should have a list of playbooks and flags ...
|
||||||
|
|||||||
@@ -18,11 +18,14 @@
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
from celery import task
|
from celery import task
|
||||||
|
from django.conf import settings
|
||||||
from lib.main.models import *
|
from lib.main.models import *
|
||||||
|
|
||||||
@task(name='run_launch_job')
|
@task(name='run_launch_job')
|
||||||
def run_launch_job(launch_job_status_pk):
|
def run_launch_job(launch_job_status_pk):
|
||||||
launch_job_status = LaunchJobStatus.objects.get(pk=launch_job_status_pk)
|
launch_job_status = LaunchJobStatus.objects.get(pk=launch_job_status_pk)
|
||||||
|
launch_job_status.status = 'running'
|
||||||
|
launch_job_status.save()
|
||||||
launch_job = launch_job_status.launch_job
|
launch_job = launch_job_status.launch_job
|
||||||
plugin_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..',
|
plugin_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..',
|
||||||
'plugins', 'callback'))
|
'plugins', 'callback'))
|
||||||
@@ -33,10 +36,20 @@ def run_launch_job(launch_job_status_pk):
|
|||||||
env['ACOM_LAUNCH_JOB_STATUS_ID'] = str(launch_job_status.pk)
|
env['ACOM_LAUNCH_JOB_STATUS_ID'] = str(launch_job_status.pk)
|
||||||
env['ACOM_INVENTORY_ID'] = str(launch_job.inventory.pk)
|
env['ACOM_INVENTORY_ID'] = str(launch_job.inventory.pk)
|
||||||
env['ANSIBLE_CALLBACK_PLUGINS'] = plugin_dir
|
env['ANSIBLE_CALLBACK_PLUGINS'] = plugin_dir
|
||||||
|
if hasattr(settings, 'ANSIBLE_TRANSPORT'):
|
||||||
|
env['ANSIBLE_TRANSPORT'] = getattr(settings, 'ANSIBLE_TRANSPORT')
|
||||||
playbook = launch_job.project.default_playbook
|
playbook = launch_job.project.default_playbook
|
||||||
cmdline = ['ansible-playbook', '-i', inventory_script, '-v']
|
cmdline = ['ansible-playbook', '-i', inventory_script]#, '-v']
|
||||||
if False: # local mode
|
|
||||||
cmdline.extend(['-c', 'local'])
|
|
||||||
cmdline.append(playbook)
|
cmdline.append(playbook)
|
||||||
subprocess.check_call(cmdline, env=env)
|
proc = subprocess.Popen(cmdline, stdout=subprocess.PIPE,
|
||||||
# FIXME: Capture stdout/stderr
|
stderr=subprocess.PIPE, env=env)
|
||||||
|
stdout, stderr = proc.communicate()
|
||||||
|
# Reload from database before updating/saving.
|
||||||
|
launch_job_status = LaunchJobStatus.objects.get(pk=launch_job_status_pk)
|
||||||
|
if proc.returncode == 0:
|
||||||
|
launch_job_status.status = 'successful'
|
||||||
|
else:
|
||||||
|
launch_job_status.status = 'failed'
|
||||||
|
launch_job_status.result_stdout = stdout
|
||||||
|
launch_job_status.result_stderr = stderr
|
||||||
|
launch_job_status.save()
|
||||||
|
|||||||
@@ -24,10 +24,13 @@ from django.test.client import Client
|
|||||||
from lib.main.models import *
|
from lib.main.models import *
|
||||||
|
|
||||||
|
|
||||||
class BaseTest(django.test.TestCase):
|
class BaseTestMixin(object):
|
||||||
|
'''
|
||||||
|
Mixin with shared code for use by all test cases.
|
||||||
|
'''
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(BaseTest, self).setUp()
|
super(BaseTestMixin, self).setUp()
|
||||||
self.object_ctr = 0
|
self.object_ctr = 0
|
||||||
|
|
||||||
def make_user(self, username, password, super_user=False):
|
def make_user(self, username, password, super_user=False):
|
||||||
@@ -131,3 +134,13 @@ class BaseTest(django.test.TestCase):
|
|||||||
data = self.get(collection_url, expect=200, auth=auth)
|
data = self.get(collection_url, expect=200, auth=auth)
|
||||||
return [item['url'] for item in data['results']]
|
return [item['url'] for item in data['results']]
|
||||||
|
|
||||||
|
class BaseTest(BaseTestMixin, django.test.TestCase):
|
||||||
|
'''
|
||||||
|
Base class for unit tests.
|
||||||
|
'''
|
||||||
|
|
||||||
|
class BaseTransactionTest(BaseTestMixin, django.test.TransactionTestCase):
|
||||||
|
'''
|
||||||
|
Base class for tests requiring transactions (or where the test database
|
||||||
|
needs to be accessed by subprocesses).
|
||||||
|
'''
|
||||||
|
|||||||
@@ -16,13 +16,72 @@
|
|||||||
# along with Ansible Commander. If not, see <http://www.gnu.org/licenses/>.
|
# along with Ansible Commander. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
from django.conf import settings
|
||||||
|
from django.test.utils import override_settings
|
||||||
from lib.main.models import *
|
from lib.main.models import *
|
||||||
from lib.main.tests.base import BaseTest
|
from lib.main.tests.base import BaseTransactionTest
|
||||||
|
|
||||||
class RunLaunchJobTest(BaseTest):
|
TEST_PLAYBOOK = '''- hosts: test-group
|
||||||
|
gather_facts: False
|
||||||
|
tasks:
|
||||||
|
- name: should pass
|
||||||
|
command: test 1 = 1
|
||||||
|
'''
|
||||||
|
|
||||||
|
@override_settings(CELERY_ALWAYS_EAGER=True,
|
||||||
|
CELERY_EAGER_PROPAGATES_EXCEPTIONS=True)
|
||||||
|
class BaseCeleryTest(BaseTransactionTest):
|
||||||
|
'''
|
||||||
|
Base class for celery task tests.
|
||||||
|
'''
|
||||||
|
|
||||||
|
@override_settings(ANSIBLE_TRANSPORT='local')
|
||||||
|
class RunLaunchJobTest(BaseCeleryTest):
|
||||||
'''
|
'''
|
||||||
Test cases for run_launch_job celery task.
|
Test cases for run_launch_job celery task.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
pass
|
super(RunLaunchJobTest, self).setUp()
|
||||||
|
self.setup_users()
|
||||||
|
self.organization = self.make_organizations(self.super_django_user, 1)[0]
|
||||||
|
self.project = self.make_projects(self.normal_django_user, 1)[0]
|
||||||
|
handle, self.test_playbook = tempfile.mkstemp(suffix='.yml', prefix='playbook-')
|
||||||
|
test_playbook_file = os.fdopen(handle, 'w')
|
||||||
|
test_playbook_file.write(TEST_PLAYBOOK)
|
||||||
|
test_playbook_file.close()
|
||||||
|
self.project.default_playbook = self.test_playbook
|
||||||
|
self.project.save()
|
||||||
|
self.organization.projects.add(self.project)
|
||||||
|
self.inventory = Inventory.objects.create(name='test-inventory',
|
||||||
|
description='description for test-inventory',
|
||||||
|
organization=self.organization)
|
||||||
|
self.host = self.inventory.hosts.create(name='host.example.com',
|
||||||
|
inventory=self.inventory)
|
||||||
|
self.group = self.inventory.groups.create(name='test-group',
|
||||||
|
inventory=self.inventory)
|
||||||
|
self.group.hosts.add(self.host)
|
||||||
|
self.launch_job = LaunchJob.objects.create(name='test-launch-job',
|
||||||
|
inventory=self.inventory,
|
||||||
|
project=self.project)
|
||||||
|
# Pass test database name in environment for use by the inventory script.
|
||||||
|
os.environ['ACOM_TEST_DATABASE_NAME'] = settings.DATABASES['default']['NAME']
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super(RunLaunchJobTest, self).tearDown()
|
||||||
|
os.environ.pop('ACOM_TEST_DATABASE_NAME', None)
|
||||||
|
os.remove(self.test_playbook)
|
||||||
|
|
||||||
|
def test_run_launch_job(self):
|
||||||
|
launch_job_status = self.launch_job.start()
|
||||||
|
self.assertEqual(launch_job_status.status, 'pending')
|
||||||
|
launch_job_status = LaunchJobStatus.objects.get(pk=launch_job_status.pk)
|
||||||
|
self.assertEqual(launch_job_status.status, 'successful')
|
||||||
|
self.assertTrue(launch_job_status.result_stdout)
|
||||||
|
#print 'stdout:', launch_job_status.result_stdout
|
||||||
|
#print 'stderr:', launch_job_status.result_stderr
|
||||||
|
|
||||||
|
# FIXME: Test with a task that fails.
|
||||||
|
# FIXME: Get callback working.
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ class CallbackModule(object):
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
def _log_event(self, event, *args, **kwargs):
|
def _log_event(self, event, *args, **kwargs):
|
||||||
print '====', event, args, kwargs
|
|
||||||
# FIXME: Push these events back to the server.
|
# FIXME: Push these events back to the server.
|
||||||
|
pass#print '====', event, args, kwargs
|
||||||
|
|
||||||
def on_any(self, *args, **kwargs):
|
def on_any(self, *args, **kwargs):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ DATABASES = {
|
|||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
'NAME': os.path.join(BASE_DIR, 'acom.sqlite3'),
|
'NAME': os.path.join(BASE_DIR, 'acom.sqlite3'),
|
||||||
|
# Test database cannot be :memory: for celery/inventory tests to work.
|
||||||
|
'TEST_NAME': os.path.join(BASE_DIR, 'acom_test.sqlite3'),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user