diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 15e66e0239..98a8896b73 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -38,7 +38,7 @@ from rest_framework.utils.serializer_helpers import ReturnList from polymorphic.models import PolymorphicModel # AWX -from awx.main.constants import SCHEDULEABLE_PROVIDERS +from awx.main.constants import SCHEDULEABLE_PROVIDERS, ANSI_SGR_PATTERN from awx.main.models import * # noqa from awx.main.access import get_user_capabilities from awx.main.fields import ImplicitRoleField @@ -3064,6 +3064,14 @@ class JobEventSerializer(BaseSerializer): max_bytes = settings.EVENT_STDOUT_MAX_BYTES_DISPLAY if max_bytes > 0 and 'stdout' in ret and len(ret['stdout']) >= max_bytes: ret['stdout'] = ret['stdout'][:(max_bytes - 1)] + u'\u2026' + set_count = 0 + 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 @@ -3095,6 +3103,14 @@ class AdHocCommandEventSerializer(BaseSerializer): max_bytes = settings.EVENT_STDOUT_MAX_BYTES_DISPLAY if max_bytes > 0 and 'stdout' in ret and len(ret['stdout']) >= max_bytes: ret['stdout'] = ret['stdout'][:(max_bytes - 1)] + u'\u2026' + set_count = 0 + 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 diff --git a/awx/main/constants.py b/awx/main/constants.py index bd00147415..10be060094 100644 --- a/awx/main/constants.py +++ b/awx/main/constants.py @@ -1,8 +1,11 @@ # Copyright (c) 2015 Ansible, Inc. # All Rights Reserved. +import re + from django.utils.translation import ugettext_lazy as _ CLOUD_PROVIDERS = ('azure', 'azure_rm', 'ec2', 'gce', 'rax', 'vmware', 'openstack', 'satellite6', 'cloudforms') SCHEDULEABLE_PROVIDERS = CLOUD_PROVIDERS + ('custom', 'scm',) PRIVILEGE_ESCALATION_METHODS = [ ('sudo', _('Sudo')), ('su', _('Su')), ('pbrun', _('Pbrun')), ('pfexec', _('Pfexec')), ('dzdo', _('DZDO')), ('pmrun', _('Pmrun')), ('runas', _('Runas'))] +ANSI_SGR_PATTERN = re.compile(r'\x1b\[[0-9;]*m')