Merge pull request #1778 from ryanpetrello/1k-ought-to-be-enough-for-anybody

truncate certain event fields when they are overly long
This commit is contained in:
Ryan Petrello
2018-05-14 14:30:42 -04:00
committed by GitHub
2 changed files with 39 additions and 14 deletions

View File

@@ -4,9 +4,11 @@ import logging
from django.conf import settings from django.conf import settings
from django.db import models, DatabaseError from django.db import models, DatabaseError
from django.utils.dateparse import parse_datetime from django.utils.dateparse import parse_datetime
from django.utils.text import Truncator
from django.utils.timezone import utc from django.utils.timezone import utc
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import force_text from django.utils.encoding import force_text
import six
from awx.api.versioning import reverse from awx.api.versioning import reverse
from awx.main.fields import JSONField from awx.main.fields import JSONField
@@ -22,6 +24,22 @@ __all__ = ['JobEvent', 'ProjectUpdateEvent', 'AdHocCommandEvent',
'InventoryUpdateEvent', 'SystemJobEvent'] 'InventoryUpdateEvent', 'SystemJobEvent']
def sanitize_event_keys(kwargs, valid_keys):
# Sanity check: Don't honor keys that we don't recognize.
for key in kwargs.keys():
if key not in valid_keys:
kwargs.pop(key)
# Truncate certain values over 1k
for key in [
'play', 'role', 'task', 'playbook'
]:
if isinstance(kwargs.get(key), six.string_types):
if len(kwargs[key]) > 1024:
kwargs[key] = Truncator(kwargs[key]).chars(1024)
class BasePlaybookEvent(CreatedModifiedModel): class BasePlaybookEvent(CreatedModifiedModel):
''' '''
An event/message logged from a playbook callback for each host. An event/message logged from a playbook callback for each host.
@@ -257,7 +275,7 @@ class BasePlaybookEvent(CreatedModifiedModel):
return updated_fields return updated_fields
@classmethod @classmethod
def create_from_data(self, **kwargs): def create_from_data(cls, **kwargs):
pk = None pk = None
for key in ('job_id', 'project_update_id'): for key in ('job_id', 'project_update_id'):
if key in kwargs: if key in kwargs:
@@ -279,12 +297,8 @@ class BasePlaybookEvent(CreatedModifiedModel):
except (KeyError, ValueError): except (KeyError, ValueError):
kwargs.pop('created', None) kwargs.pop('created', None)
# Sanity check: Don't honor keys that we don't recognize. sanitize_event_keys(kwargs, cls.VALID_KEYS)
for key in kwargs.keys(): job_event = cls.objects.create(**kwargs)
if key not in self.VALID_KEYS:
kwargs.pop(key)
job_event = self.objects.create(**kwargs)
analytics_logger.info('Event data saved.', extra=dict(python_objects=dict(job_event=job_event))) analytics_logger.info('Event data saved.', extra=dict(python_objects=dict(job_event=job_event)))
return job_event return job_event
@@ -551,7 +565,7 @@ class BaseCommandEvent(CreatedModifiedModel):
return u'%s @ %s' % (self.get_event_display(), self.created.isoformat()) return u'%s @ %s' % (self.get_event_display(), self.created.isoformat())
@classmethod @classmethod
def create_from_data(self, **kwargs): def create_from_data(cls, **kwargs):
# Convert the datetime for the event's creation # Convert the datetime for the event's creation
# appropriately, and include a time zone for it. # appropriately, and include a time zone for it.
# #
@@ -565,12 +579,8 @@ class BaseCommandEvent(CreatedModifiedModel):
except (KeyError, ValueError): except (KeyError, ValueError):
kwargs.pop('created', None) kwargs.pop('created', None)
# Sanity check: Don't honor keys that we don't recognize. sanitize_event_keys(kwargs, cls.VALID_KEYS)
for key in kwargs.keys(): return cls.objects.create(**kwargs)
if key not in self.VALID_KEYS:
kwargs.pop(key)
return self.objects.create(**kwargs)
def get_event_display(self): def get_event_display(self):
''' '''

View File

@@ -44,3 +44,18 @@ def test_playbook_event_strip_invalid_keys(job_identifier, cls):
'extra_key': 'extra_value' 'extra_key': 'extra_value'
}) })
manager.create.assert_called_with(**{job_identifier: 123}) manager.create.assert_called_with(**{job_identifier: 123})
@pytest.mark.parametrize('field', [
'play', 'role', 'task', 'playbook'
])
def test_really_long_event_fields(field):
with mock.patch.object(JobEvent, 'objects') as manager:
JobEvent.create_from_data(**{
'job_id': 123,
field: 'X' * 4096
})
manager.create.assert_called_with(**{
'job_id': 123,
field: 'X' * 1021 + '...'
})