Merge pull request #2070 from chrismeyersfsu/fix-controller_node_not_needed_on_some_jobs

remove controller_node field from jobs that don't apply
This commit is contained in:
Chris Meyers
2018-06-06 16:19:00 -04:00
committed by GitHub
4 changed files with 84 additions and 30 deletions

View File

@@ -1400,7 +1400,7 @@ class ProjectUpdateSerializer(UnifiedJobSerializer, ProjectOptionsSerializer):
class Meta: class Meta:
model = ProjectUpdate model = ProjectUpdate
fields = ('*', 'project', 'job_type') fields = ('*', 'project', 'job_type', '-controller_node')
def get_related(self, obj): def get_related(self, obj):
res = super(ProjectUpdateSerializer, self).get_related(obj) res = super(ProjectUpdateSerializer, self).get_related(obj)
@@ -2110,7 +2110,8 @@ class InventoryUpdateSerializer(UnifiedJobSerializer, InventorySourceOptionsSeri
class Meta: class Meta:
model = InventoryUpdate model = InventoryUpdate
fields = ('*', 'inventory_source', 'license_error', 'source_project_update') fields = ('*', 'inventory_source', 'license_error', 'source_project_update',
'-controller_node',)
def get_related(self, obj): def get_related(self, obj):
res = super(InventoryUpdateSerializer, self).get_related(obj) res = super(InventoryUpdateSerializer, self).get_related(obj)
@@ -3257,7 +3258,8 @@ class AdHocCommandSerializer(UnifiedJobSerializer):
model = AdHocCommand model = AdHocCommand
fields = ('*', 'job_type', 'inventory', 'limit', 'credential', fields = ('*', 'job_type', 'inventory', 'limit', 'credential',
'module_name', 'module_args', 'forks', 'verbosity', 'extra_vars', 'module_name', 'module_args', 'forks', 'verbosity', 'extra_vars',
'become_enabled', 'diff_mode', '-unified_job_template', '-description') 'become_enabled', 'diff_mode', '-unified_job_template', '-description',
'-controller_node',)
extra_kwargs = { extra_kwargs = {
'name': { 'name': {
'read_only': True, 'read_only': True,
@@ -3366,7 +3368,7 @@ class SystemJobSerializer(UnifiedJobSerializer):
class Meta: class Meta:
model = SystemJob model = SystemJob
fields = ('*', 'system_job_template', 'job_type', 'extra_vars', 'result_stdout') fields = ('*', 'system_job_template', 'job_type', 'extra_vars', 'result_stdout', '-controller_node',)
def get_related(self, obj): def get_related(self, obj):
res = super(SystemJobSerializer, self).get_related(obj) res = super(SystemJobSerializer, self).get_related(obj)

View File

@@ -9,7 +9,13 @@ from rest_framework.exceptions import PermissionDenied
from awx.api.versioning import reverse from awx.api.versioning import reverse
from awx.api.views import RelatedJobsPreventDeleteMixin, UnifiedJobDeletionMixin from awx.api.views import RelatedJobsPreventDeleteMixin, UnifiedJobDeletionMixin
from awx.main.models import JobTemplate, User, Job from awx.main.models import (
JobTemplate,
User,
Job,
AdHocCommand,
ProjectUpdate,
)
from crum import impersonate from crum import impersonate
@@ -159,3 +165,41 @@ def test_block_related_unprocessed_events(mocker, organization, project, delete,
with mock.patch('awx.api.views.now', lambda: time_of_request): with mock.patch('awx.api.views.now', lambda: time_of_request):
with pytest.raises(PermissionDenied): with pytest.raises(PermissionDenied):
view.perform_destroy(organization) view.perform_destroy(organization)
class TestControllerNode():
@pytest.fixture
def project_update(self, project):
return ProjectUpdate.objects.create(project=project)
@pytest.fixture
def job(self):
return JobTemplate.objects.create().create_unified_job()
@pytest.fixture
def adhoc(self, inventory):
return AdHocCommand.objects.create(inventory=inventory)
@pytest.mark.django_db
def test_field_controller_node_exists(self, sqlite_copy_expert,
admin_user, job, project_update,
inventory_update, adhoc, get, system_job_factory):
system_job = system_job_factory()
r = get(reverse('api:unified_job_list') + '?id={}'.format(job.id), admin_user, expect=200)
assert 'controller_node' in r.data['results'][0]
r = get(job.get_absolute_url(), admin_user, expect=200)
assert 'controller_node' in r.data
r = get(reverse('api:project_update_detail', kwargs={'pk': project_update.pk}), admin_user, expect=200)
assert 'controller_node' not in r.data
r = get(reverse('api:ad_hoc_command_detail', kwargs={'pk': adhoc.pk}), admin_user, expect=200)
assert 'controller_node' not in r.data
r = get(reverse('api:inventory_update_detail', kwargs={'pk': inventory_update.pk}), admin_user, expect=200)
assert 'controller_node' not in r.data
r = get(reverse('api:system_job_detail', kwargs={'pk': system_job.pk}), admin_user, expect=200)
assert 'controller_node' not in r.data

View File

@@ -3,11 +3,8 @@
import base64 import base64
import json import json
import re import re
import shutil
import tempfile
from django.conf import settings from django.conf import settings
from django.db.backends.sqlite3.base import SQLiteCursorWrapper
import mock import mock
import pytest import pytest
@@ -31,28 +28,6 @@ def _mk_inventory_update():
return iu return iu
@pytest.fixture(scope='function')
def sqlite_copy_expert(request):
# copy_expert is postgres-specific, and SQLite doesn't support it; mock its
# behavior to test that it writes a file that contains stdout from events
path = tempfile.mkdtemp(prefix='job-event-stdout')
def write_stdout(self, sql, fd):
# simulate postgres copy_expert support with ORM code
parts = sql.split(' ')
tablename = parts[parts.index('from') + 1]
for cls in (JobEvent, AdHocCommandEvent, ProjectUpdateEvent,
InventoryUpdateEvent, SystemJobEvent):
if cls._meta.db_table == tablename:
for event in cls.objects.order_by('start_line').all():
fd.write(event.stdout.encode('utf-8'))
setattr(SQLiteCursorWrapper, 'copy_expert', write_stdout)
request.addfinalizer(lambda: shutil.rmtree(path))
request.addfinalizer(lambda: delattr(SQLiteCursorWrapper, 'copy_expert'))
return path
@pytest.mark.django_db @pytest.mark.django_db
@pytest.mark.parametrize('Parent, Child, relation, view', [ @pytest.mark.parametrize('Parent, Child, relation, view', [
[Job, JobEvent, 'job', 'api:job_stdout'], [Job, JobEvent, 'job', 'api:job_stdout'],

View File

@@ -4,6 +4,8 @@ import mock
import json import json
import os import os
import six import six
import tempfile
import shutil
from datetime import timedelta from datetime import timedelta
from six.moves import xrange from six.moves import xrange
@@ -14,6 +16,7 @@ from django.utils import timezone
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.conf import settings from django.conf import settings
from django.core.serializers.json import DjangoJSONEncoder from django.core.serializers.json import DjangoJSONEncoder
from django.db.backends.sqlite3.base import SQLiteCursorWrapper
from jsonbfield.fields import JSONField from jsonbfield.fields import JSONField
# AWX # AWX
@@ -44,6 +47,13 @@ from awx.main.models.notifications import (
NotificationTemplate, NotificationTemplate,
Notification Notification
) )
from awx.main.models.events import (
JobEvent,
AdHocCommandEvent,
ProjectUpdateEvent,
InventoryUpdateEvent,
SystemJobEvent,
)
from awx.main.models.workflow import WorkflowJobTemplate from awx.main.models.workflow import WorkflowJobTemplate
from awx.main.models.ad_hoc_commands import AdHocCommand from awx.main.models.ad_hoc_commands import AdHocCommand
from awx.main.models.oauth import OAuth2Application as Application from awx.main.models.oauth import OAuth2Application as Application
@@ -729,3 +739,26 @@ def oauth_application(admin):
name='test app', user=admin, client_type='confidential', name='test app', user=admin, client_type='confidential',
authorization_grant_type='password' authorization_grant_type='password'
) )
@pytest.fixture
def sqlite_copy_expert(request):
# copy_expert is postgres-specific, and SQLite doesn't support it; mock its
# behavior to test that it writes a file that contains stdout from events
path = tempfile.mkdtemp(prefix='job-event-stdout')
def write_stdout(self, sql, fd):
# simulate postgres copy_expert support with ORM code
parts = sql.split(' ')
tablename = parts[parts.index('from') + 1]
for cls in (JobEvent, AdHocCommandEvent, ProjectUpdateEvent,
InventoryUpdateEvent, SystemJobEvent):
if cls._meta.db_table == tablename:
for event in cls.objects.order_by('start_line').all():
fd.write(event.stdout.encode('utf-8'))
setattr(SQLiteCursorWrapper, 'copy_expert', write_stdout)
request.addfinalizer(lambda: shutil.rmtree(path))
request.addfinalizer(lambda: delattr(SQLiteCursorWrapper, 'copy_expert'))
return path