Skip to content

Commit

Permalink
Merge pull request #91 from rundeck-plugins/rse241-win12-node-takes-w…
Browse files Browse the repository at this point in the history
…rong-out-charset

RSE-241: Fix: Using wrong charset to print output on windows 12 japanese nodes
  • Loading branch information
L2JE authored Jan 17, 2023
2 parents 8e67b09 + 38d1fed commit 5c003dc
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 16 deletions.
16 changes: 9 additions & 7 deletions contents/winrm-exec.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import common
from colored_formatter import ColoredFormatter


class SuppressFilter(logging.Filter):
def filter(self, record):
return 'wsman' not in record.getMessage()
Expand Down Expand Up @@ -210,6 +209,10 @@ def filter(self, record):
else:
krbdelegation = False

output_charset = "utf-8"
if "RD_NODE_OUTPUT_CHARSET" in os.environ:
output_charset = os.getenv("RD_NODE_OUTPUT_CHARSET")

log.debug("------------------------------------------")
log.debug("endpoint:" + endpoint)
log.debug("authentication:" + authentication)
Expand All @@ -220,6 +223,7 @@ def filter(self, record):
log.debug("kinit command:" + kinit)
log.debug("kerberos delegation:" + str(krbdelegation))
log.debug("shell:" + shell)
log.debug("output_charset:" + output_charset)
log.debug("readtimeout:" + str(readtimeout))
log.debug("operationtimeout:" + str(operationtimeout))
log.debug("exit Behaviour:" + exitBehaviour)
Expand Down Expand Up @@ -282,7 +286,7 @@ def filter(self, record):
winrm.Session._clean_error_msg = winrm_session._clean_error_msg
winrm.Session._strip_namespace = winrm_session._strip_namespace

tsk = winrm_session.RunCommand(session, shell, exec_command)
tsk = winrm_session.RunCommand(session, shell, exec_command, output_charset)
t = threading.Thread(target=tsk.get_response)
t.start()
realstdout = sys.stdout
Expand All @@ -293,10 +297,6 @@ def filter(self, record):
lastpos = 0
lasterrorpos = 0

charset = "utf-8"
if "RD_NODE_CHARSET" in os.environ:
charset = os.getenv("RD_NODE_CHARSET")

while True:
t.join(.1)

Expand All @@ -306,7 +306,7 @@ def filter(self, record):
if isinstance(read, str):
realstdout.write(read)
else:
realstdout.write(read.decode(charset))
realstdout.write(read.decode(output_charset))

lastpos = sys.stdout.tell()

Expand All @@ -318,6 +318,8 @@ def filter(self, record):
sys.stdout = realstdout
sys.stderr = realstderr



if exitBehaviour == 'console':
if tsk.e_std:
log.error("Execution finished with the following error")
Expand Down
19 changes: 10 additions & 9 deletions contents/winrm_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@

# TODO: this PR https://github.com/diyan/pywinrm/pull/55 will add this fix.
# when this PR is merged, this won't be needed anymore
def run_cmd(self, command, args=(), out_stream=None, err_stream=None):
def run_cmd(self, command, args=(), out_stream=None, err_stream=None, output_charset='utf-8'):
self.protocol.get_command_output = protocol.get_command_output
winrm.Session._clean_error_msg = self._clean_error_msg

Expand All @@ -63,28 +63,28 @@ def run_cmd(self, command, args=(), out_stream=None, err_stream=None):
command_id = self.protocol.run_command(shell_id, command, args)
rs = Response(self.protocol.get_command_output(self.protocol, shell_id, command_id, out_stream, err_stream))

error = self._clean_error_msg(rs.std_err)
error = self._clean_error_msg(rs.std_err, output_charset)
rs.std_err = error

self.protocol.cleanup_command(shell_id, command_id)
self.protocol.close_shell(shell_id)
return rs


def run_ps(self, script, out_stream=None, err_stream=None):
def run_ps(self, script, out_stream=None, err_stream=None, output_charset='utf-8'):
"""base64 encodes a Powershell script and executes the powershell
encoded script command
"""
script = to_text(script)
encoded_ps = base64.b64encode(script.encode('utf_16_le')).decode('ascii')
rs = self.run_cmd('powershell -encodedcommand {0}'.format(encoded_ps),out_stream=out_stream, err_stream=err_stream)
rs = self.run_cmd('powershell -encodedcommand {0}'.format(encoded_ps),out_stream=out_stream, err_stream=err_stream, output_charset=output_charset)

return rs


def _clean_error_msg(self, msg):
def _clean_error_msg(self, msg, encoding='utf-8'):
#data=""
msg = to_text(msg)
msg = to_text(msg, encoding)

if msg.startswith("#< CLIXML") or "<Objs Version=" in msg or "-1</PI><PC>" in msg:
# for proper xml, we need to remove the CLIXML part
Expand Down Expand Up @@ -135,24 +135,25 @@ def __repr__(self):


class RunCommand:
def __init__(self, session, shell, command ):
def __init__(self, session, shell, command, output_charset='utf-8'):
self.stat, self.o_std, self.e_std = None, None, None
self.o_stream = BytesIO()
self.e_stream = BytesIO()
self.session = session
self.exec_command = command
self.shell = shell
self.output_charset = output_charset

def get_response(self):
try:
if self.shell == "cmd":
response = self.session.run_cmd(self.exec_command, out_stream=self.o_stream, err_stream=self.e_stream)
response = self.session.run_cmd(self.exec_command, out_stream=self.o_stream, err_stream=self.e_stream, output_charset=self.output_charset)
self.o_std = response.std_out
self.e_std = response.std_err
self.stat = response.status_code

if self.shell == "powershell":
response = self.session.run_ps(self.exec_command, out_stream=self.o_stream, err_stream=self.e_stream)
response = self.session.run_ps(self.exec_command, out_stream=self.o_stream, err_stream=self.e_stream, output_charset=self.output_charset)
self.o_std = response.std_out
self.e_std = response.std_err
self.stat = response.status_code
Expand Down

0 comments on commit 5c003dc

Please sign in to comment.