diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ce9fd132d2..8f530b8d44 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -53,6 +53,11 @@ Fixed * StackStorm now explicitly decodes pack files as utf-8 instead of implicitly as ascii (bug fix) #5106, #5107 +* Fix ``@parameter_name=/path/to/file/foo.json`` notation in the ``st2 run`` command which didn't + work correctly because it didn't convert read bytes to string / unicode type. (bug fix) #5140 + + Contributed by @Kami. + * Fix broken ``st2 action-alias execute`` command and make sure it works correctly. (bug fix) #5138 diff --git a/st2client/st2client/commands/action.py b/st2client/st2client/commands/action.py index d23fe583d2..7a41d9e2eb 100644 --- a/st2client/st2client/commands/action.py +++ b/st2client/st2client/commands/action.py @@ -541,6 +541,12 @@ def _get_action_parameters_from_args(self, action, runner, args): action_ref_or_id = action.ref def read_file(file_path): + """ + Read file content and return content as string / unicode. + + NOTE: It's only mean to be used to read non-binary files since API right now doesn't + support passing binary data. + """ if not os.path.exists(file_path): raise ValueError('File "%s" doesn\'t exist' % (file_path)) @@ -550,7 +556,7 @@ def read_file(file_path): with open(file_path, 'rb') as fp: content = fp.read() - return content + return content.decode("utf-8") def transform_object(value): # Also support simple key1=val1,key2=val2 syntax diff --git a/st2client/tests/unit/test_command_actionrun.py b/st2client/tests/unit/test_command_actionrun.py index 4163b98ca5..763ac649a6 100644 --- a/st2client/tests/unit/test_command_actionrun.py +++ b/st2client/tests/unit/test_command_actionrun.py @@ -17,6 +17,7 @@ import copy import unittest2 +import six import mock from st2client.commands.action import ActionRunCommand @@ -161,6 +162,44 @@ def test_get_params_from_args(self): # set auto_dict back to default mockarg.auto_dict = False + def test_get_params_from_args_read_content_from_file(self): + runner = RunnerType() + runner.runner_parameters = {} + + action = Action() + action.ref = 'test.action' + action.parameters = { + 'param_object': {'type': 'object'}, + } + + subparser = mock.Mock() + command = ActionRunCommand(action, self, subparser, name='test') + + # 1. File doesn't exist + mockarg = mock.Mock() + mockarg.inherit_env = False + mockarg.auto_dict = True + mockarg.parameters = [ + '@param_object=doesnt-exist.json' + ] + + self.assertRaisesRegex(ValueError, "doesn't exist", + command._get_action_parameters_from_args, action=action, + runner=runner, args=mockarg) + + # 2. Valid file path (we simply read this file) + mockarg = mock.Mock() + mockarg.inherit_env = False + mockarg.auto_dict = True + mockarg.parameters = [ + '@param_string=%s' % (__file__) + ] + + params = command._get_action_parameters_from_args(action=action, + runner=runner, args=mockarg) + self.assertTrue(isinstance(params["param_string"], six.text_type)) + self.assertTrue(params["param_string"].startswith("# Copyright")) + def test_get_params_from_args_with_multiple_declarations(self): """test_get_params_from_args_with_multiple_declarations