From 66d3159525154f295bc09e0964d26dea6602e5cd Mon Sep 17 00:00:00 2001 From: Andrew Vaillancourt Date: Wed, 26 Mar 2025 16:05:58 -0400 Subject: [PATCH] Strip ANSI sequences from interactive SSH sessions - Add _strip_ansi_sequences() to remove terminal formatting characters from SSH output when using invoke_shell(). - Integrate cleanup in __read_from_channel(), affecting send_as_sudo() and send_expect_prompts() while preserving exec_command() behavior. - Centralizes ANSI cleanup logic to ensure clean logs and robust parsing. Tested: - Validated across full sanity and sanity_regression suites. - Compared logs before and after change: - Over 50 instances of ANSI sequences removed. - No regressions introduced. - Verified pass/fail parity across all tests. Change-Id: I20c8b87b3684742b82cbd29e240d61f17103691a Signed-off-by: Andrew Vaillancourt --- framework/ssh/ssh_connection.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/framework/ssh/ssh_connection.py b/framework/ssh/ssh_connection.py index 47630260..a7a6cb3e 100644 --- a/framework/ssh/ssh_connection.py +++ b/framework/ssh/ssh_connection.py @@ -1,4 +1,5 @@ import codecs +import re import time from typing import List @@ -401,6 +402,10 @@ class SSHConnection: # Convert the buffer to our chosen encoding current_buffer_decoded = decoder.decode(current_buffer) + # Strip ANSI escape sequences added by shell commands like sudo or colored prompts + # These sequences are common in interactive `invoke_shell()` sessions + current_buffer_decoded = self._strip_ansi_sequences(current_buffer_decoded) + # Strip all ugly \r (Ctrl-M making) characters from the current read current_buffer_decoded = current_buffer_decoded.replace("\r", "") @@ -508,3 +513,25 @@ class SSHConnection: str: A string identifying this SSH connection. """ return f"ssh_con:{self.name}" + + @staticmethod + def _strip_ansi_sequences(text: str) -> str: + """ + Remove ANSI escape sequences from a string. + + This is a commonly used regular expression for matching ANSI terminal + control codes (e.g., color codes, cursor movement, etc.). These are + typically found in output from interactive shell commands. + + Regex pattern adapted from: + - https://stackoverflow.com/a/14693789 + - https://github.com/chalk/ansi-regex/blob/main/index.js + + Args: + text (str): A string that may contain ANSI escape sequences. + + Returns: + str: Cleaned string without ANSI sequences. + """ + ansi_escape_pattern = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])") + return ansi_escape_pattern.sub("", text)