mirror of
https://github.com/ansible/awx.git
synced 2026-03-10 14:09:28 -02:30
Break out a new reusable truncate_stdout utility function
This commit is contained in:
@@ -45,7 +45,6 @@ from polymorphic.models import PolymorphicModel
|
|||||||
from awx.main.access import get_user_capabilities
|
from awx.main.access import get_user_capabilities
|
||||||
from awx.main.constants import (
|
from awx.main.constants import (
|
||||||
SCHEDULEABLE_PROVIDERS,
|
SCHEDULEABLE_PROVIDERS,
|
||||||
ANSI_SGR_PATTERN,
|
|
||||||
ACTIVE_STATES,
|
ACTIVE_STATES,
|
||||||
CENSOR_VALUE,
|
CENSOR_VALUE,
|
||||||
)
|
)
|
||||||
@@ -70,7 +69,8 @@ from awx.main.utils import (
|
|||||||
get_type_for_model, get_model_for_type,
|
get_type_for_model, get_model_for_type,
|
||||||
camelcase_to_underscore, getattrd, parse_yaml_or_json,
|
camelcase_to_underscore, getattrd, parse_yaml_or_json,
|
||||||
has_model_field_prefetched, extract_ansible_vars, encrypt_dict,
|
has_model_field_prefetched, extract_ansible_vars, encrypt_dict,
|
||||||
prefetch_page_capabilities, get_external_account)
|
prefetch_page_capabilities, get_external_account, truncate_stdout,
|
||||||
|
)
|
||||||
from awx.main.utils.filters import SmartFilter
|
from awx.main.utils.filters import SmartFilter
|
||||||
from awx.main.redact import UriCleaner, REPLACE_STR
|
from awx.main.redact import UriCleaner, REPLACE_STR
|
||||||
|
|
||||||
@@ -3851,25 +3851,17 @@ class JobEventSerializer(BaseSerializer):
|
|||||||
return d
|
return d
|
||||||
|
|
||||||
def to_representation(self, obj):
|
def to_representation(self, obj):
|
||||||
ret = super(JobEventSerializer, self).to_representation(obj)
|
data = super(JobEventSerializer, self).to_representation(obj)
|
||||||
# Show full stdout for event detail view, truncate only for list view.
|
# Show full stdout for event detail view, truncate only for list view.
|
||||||
if hasattr(self.context.get('view', None), 'retrieve'):
|
if hasattr(self.context.get('view', None), 'retrieve'):
|
||||||
return ret
|
return data
|
||||||
# Show full stdout for playbook_on_* events.
|
# Show full stdout for playbook_on_* events.
|
||||||
if obj and obj.event.startswith('playbook_on'):
|
if obj and obj.event.startswith('playbook_on'):
|
||||||
return ret
|
return data
|
||||||
max_bytes = settings.EVENT_STDOUT_MAX_BYTES_DISPLAY
|
max_bytes = settings.EVENT_STDOUT_MAX_BYTES_DISPLAY
|
||||||
if max_bytes > 0 and 'stdout' in ret and len(ret['stdout']) >= max_bytes:
|
if 'stdout' in data:
|
||||||
ret['stdout'] = ret['stdout'][:(max_bytes - 1)] + u'\u2026'
|
data['stdout'] = truncate_stdout(data['stdout'], max_bytes)
|
||||||
set_count = 0
|
return data
|
||||||
reset_count = 0
|
|
||||||
for m in ANSI_SGR_PATTERN.finditer(ret['stdout']):
|
|
||||||
if m.string[m.start():m.end()] == u'\u001b[0m':
|
|
||||||
reset_count += 1
|
|
||||||
else:
|
|
||||||
set_count += 1
|
|
||||||
ret['stdout'] += u'\u001b[0m' * (set_count - reset_count)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
class JobEventWebSocketSerializer(JobEventSerializer):
|
class JobEventWebSocketSerializer(JobEventSerializer):
|
||||||
@@ -3964,22 +3956,14 @@ class AdHocCommandEventSerializer(BaseSerializer):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
def to_representation(self, obj):
|
def to_representation(self, obj):
|
||||||
ret = super(AdHocCommandEventSerializer, self).to_representation(obj)
|
data = super(AdHocCommandEventSerializer, self).to_representation(obj)
|
||||||
# Show full stdout for event detail view, truncate only for list view.
|
# Show full stdout for event detail view, truncate only for list view.
|
||||||
if hasattr(self.context.get('view', None), 'retrieve'):
|
if hasattr(self.context.get('view', None), 'retrieve'):
|
||||||
return ret
|
return data
|
||||||
max_bytes = settings.EVENT_STDOUT_MAX_BYTES_DISPLAY
|
max_bytes = settings.EVENT_STDOUT_MAX_BYTES_DISPLAY
|
||||||
if max_bytes > 0 and 'stdout' in ret and len(ret['stdout']) >= max_bytes:
|
if 'stdout' in data:
|
||||||
ret['stdout'] = ret['stdout'][:(max_bytes - 1)] + u'\u2026'
|
data['stdout'] = truncate_stdout(data['stdout'], max_bytes)
|
||||||
set_count = 0
|
return data
|
||||||
reset_count = 0
|
|
||||||
for m in ANSI_SGR_PATTERN.finditer(ret['stdout']):
|
|
||||||
if m.string[m.start():m.end()] == u'\u001b[0m':
|
|
||||||
reset_count += 1
|
|
||||||
else:
|
|
||||||
set_count += 1
|
|
||||||
ret['stdout'] += u'\u001b[0m' * (set_count - reset_count)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
class AdHocCommandEventWebSocketSerializer(AdHocCommandEventSerializer):
|
class AdHocCommandEventWebSocketSerializer(AdHocCommandEventSerializer):
|
||||||
|
|||||||
@@ -38,18 +38,22 @@ from django.apps import apps
|
|||||||
|
|
||||||
logger = logging.getLogger('awx.main.utils')
|
logger = logging.getLogger('awx.main.utils')
|
||||||
|
|
||||||
__all__ = ['get_object_or_400', 'camelcase_to_underscore', 'underscore_to_camelcase', 'memoize', 'memoize_delete',
|
__all__ = [
|
||||||
'get_ansible_version', 'get_ssh_version', 'get_licenser', 'get_awx_version', 'update_scm_url',
|
'get_object_or_400', 'camelcase_to_underscore', 'underscore_to_camelcase', 'memoize',
|
||||||
'get_type_for_model', 'get_model_for_type', 'copy_model_by_class', 'region_sorting',
|
'memoize_delete', 'get_ansible_version', 'get_ssh_version', 'get_licenser',
|
||||||
'copy_m2m_relationships', 'prefetch_page_capabilities', 'to_python_boolean',
|
'get_awx_version', 'update_scm_url', 'get_type_for_model', 'get_model_for_type',
|
||||||
'ignore_inventory_computed_fields', 'ignore_inventory_group_removal',
|
'copy_model_by_class', 'region_sorting', 'copy_m2m_relationships',
|
||||||
'_inventory_updates', 'get_pk_from_dict', 'getattrd', 'getattr_dne', 'NoDefaultProvided',
|
'prefetch_page_capabilities', 'to_python_boolean', 'ignore_inventory_computed_fields',
|
||||||
'get_current_apps', 'set_current_apps',
|
'ignore_inventory_group_removal', '_inventory_updates', 'get_pk_from_dict', 'getattrd',
|
||||||
'extract_ansible_vars', 'get_search_fields', 'get_system_task_capacity', 'get_cpu_capacity', 'get_mem_capacity',
|
'getattr_dne', 'NoDefaultProvided', 'get_current_apps', 'set_current_apps',
|
||||||
'wrap_args_with_proot', 'build_proot_temp_dir', 'check_proot_installed', 'model_to_dict',
|
'extract_ansible_vars', 'get_search_fields', 'get_system_task_capacity',
|
||||||
'NullablePromptPseudoField', 'model_instance_diff', 'parse_yaml_or_json', 'RequireDebugTrueOrTest',
|
'get_cpu_capacity', 'get_mem_capacity', 'wrap_args_with_proot', 'build_proot_temp_dir',
|
||||||
'has_model_field_prefetched', 'set_environ', 'IllegalArgumentError', 'get_custom_venv_choices', 'get_external_account',
|
'check_proot_installed', 'model_to_dict', 'NullablePromptPseudoField',
|
||||||
'task_manager_bulk_reschedule', 'schedule_task_manager', 'classproperty', 'create_temporary_fifo']
|
'model_instance_diff', 'parse_yaml_or_json', 'RequireDebugTrueOrTest',
|
||||||
|
'has_model_field_prefetched', 'set_environ', 'IllegalArgumentError',
|
||||||
|
'get_custom_venv_choices', 'get_external_account', 'task_manager_bulk_reschedule',
|
||||||
|
'schedule_task_manager', 'classproperty', 'create_temporary_fifo', 'truncate_stdout',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def get_object_or_400(klass, *args, **kwargs):
|
def get_object_or_400(klass, *args, **kwargs):
|
||||||
@@ -1088,3 +1092,19 @@ def create_temporary_fifo(data):
|
|||||||
).start()
|
).start()
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def truncate_stdout(stdout, size):
|
||||||
|
from awx.main.constants import ANSI_SGR_PATTERN
|
||||||
|
|
||||||
|
if size <= 0 or len(stdout) <= size:
|
||||||
|
return stdout
|
||||||
|
|
||||||
|
stdout = stdout[:(size - 1)] + u'\u2026'
|
||||||
|
set_count, reset_count = 0, 0
|
||||||
|
for m in ANSI_SGR_PATTERN.finditer(stdout):
|
||||||
|
if m.group() == u'\u001b[0m':
|
||||||
|
reset_count += 1
|
||||||
|
else:
|
||||||
|
set_count += 1
|
||||||
|
|
||||||
|
return stdout + u'\u001b[0m' * (set_count - reset_count)
|
||||||
|
|||||||
Reference in New Issue
Block a user