mirror of
https://github.com/ansible/awx.git
synced 2026-02-26 23:46:05 -03:30
[Bug Fix 4.6] AAP-49077 Task stdout escapes quotes twice only with Controller API api/v2/jobs/{id}/stdout/?format=txt (#7071)
* Move logic to unified job model instead of view * Refine logic to only apply to double escaped characters to prevent touching unicord chars * Refine logic to only apply to stdout so that it does not impact webhook notifications * Revise naming to reflect correction to escapes, not just escape quotes * Update code comments to reflect fixing double escapes vs double escaped quotes specifically * Add regex for 5 most common python escape chars to make fix more robust
This commit is contained in:
@@ -1197,6 +1197,13 @@ class UnifiedJob(
|
|||||||
fd = StringIO(fd.getvalue().replace('\\r\\n', '\n'))
|
fd = StringIO(fd.getvalue().replace('\\r\\n', '\n'))
|
||||||
return fd
|
return fd
|
||||||
|
|
||||||
|
def _fix_double_escapes(self, content):
|
||||||
|
"""
|
||||||
|
Collapse double-escaped sequences into single-escaped form.
|
||||||
|
"""
|
||||||
|
# Replace \\ followed by one of ' " \ n r t
|
||||||
|
return re.sub(r'\\([\'"\\nrt])', r'\1', content)
|
||||||
|
|
||||||
def _escape_ascii(self, content):
|
def _escape_ascii(self, content):
|
||||||
# Remove ANSI escape sequences used to embed event data.
|
# Remove ANSI escape sequences used to embed event data.
|
||||||
content = re.sub(r'\x1b\[K(?:[A-Za-z0-9+/=]+\x1b\[\d+D)+\x1b\[K', '', content)
|
content = re.sub(r'\x1b\[K(?:[A-Za-z0-9+/=]+\x1b\[\d+D)+\x1b\[K', '', content)
|
||||||
@@ -1204,12 +1211,14 @@ class UnifiedJob(
|
|||||||
content = re.sub(r'\x1b[^m]*m', '', content)
|
content = re.sub(r'\x1b[^m]*m', '', content)
|
||||||
return content
|
return content
|
||||||
|
|
||||||
def _result_stdout_raw(self, redact_sensitive=False, escape_ascii=False):
|
def _result_stdout_raw(self, redact_sensitive=False, escape_ascii=False, fix_escapes=False):
|
||||||
content = self.result_stdout_raw_handle().read()
|
content = self.result_stdout_raw_handle().read()
|
||||||
if redact_sensitive:
|
if redact_sensitive:
|
||||||
content = UriCleaner.remove_sensitive(content)
|
content = UriCleaner.remove_sensitive(content)
|
||||||
if escape_ascii:
|
if escape_ascii:
|
||||||
content = self._escape_ascii(content)
|
content = self._escape_ascii(content)
|
||||||
|
if fix_escapes:
|
||||||
|
content = self._fix_double_escapes(content)
|
||||||
return content
|
return content
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -1218,9 +1227,10 @@ class UnifiedJob(
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def result_stdout(self):
|
def result_stdout(self):
|
||||||
return self._result_stdout_raw(escape_ascii=True)
|
# Human-facing output should fix escapes
|
||||||
|
return self._result_stdout_raw(escape_ascii=True, fix_escapes=True)
|
||||||
|
|
||||||
def _result_stdout_raw_limited(self, start_line=0, end_line=None, redact_sensitive=True, escape_ascii=False):
|
def _result_stdout_raw_limited(self, start_line=0, end_line=None, redact_sensitive=True, escape_ascii=False, fix_escapes=False):
|
||||||
return_buffer = StringIO()
|
return_buffer = StringIO()
|
||||||
if end_line is not None:
|
if end_line is not None:
|
||||||
end_line = int(end_line)
|
end_line = int(end_line)
|
||||||
@@ -1243,14 +1253,18 @@ class UnifiedJob(
|
|||||||
return_buffer = UriCleaner.remove_sensitive(return_buffer)
|
return_buffer = UriCleaner.remove_sensitive(return_buffer)
|
||||||
if escape_ascii:
|
if escape_ascii:
|
||||||
return_buffer = self._escape_ascii(return_buffer)
|
return_buffer = self._escape_ascii(return_buffer)
|
||||||
|
if fix_escapes:
|
||||||
|
return_buffer = self._fix_double_escapes(return_buffer)
|
||||||
|
|
||||||
return return_buffer, start_actual, end_actual, absolute_end
|
return return_buffer, start_actual, end_actual, absolute_end
|
||||||
|
|
||||||
def result_stdout_raw_limited(self, start_line=0, end_line=None, redact_sensitive=False):
|
def result_stdout_raw_limited(self, start_line=0, end_line=None, redact_sensitive=False):
|
||||||
|
# Raw should NOT fix escapes
|
||||||
return self._result_stdout_raw_limited(start_line, end_line, redact_sensitive)
|
return self._result_stdout_raw_limited(start_line, end_line, redact_sensitive)
|
||||||
|
|
||||||
def result_stdout_limited(self, start_line=0, end_line=None, redact_sensitive=False):
|
def result_stdout_limited(self, start_line=0, end_line=None, redact_sensitive=False):
|
||||||
return self._result_stdout_raw_limited(start_line, end_line, redact_sensitive, escape_ascii=True)
|
# Human-facing should fix escapes
|
||||||
|
return self._result_stdout_raw_limited(start_line, end_line, redact_sensitive, escape_ascii=True, fix_escapes=True)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def workflow_job_id(self):
|
def workflow_job_id(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user