diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 94db66b6db..ce9fd132d2 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 broken ``st2 action-alias execute`` command and make sure it works + correctly. (bug fix) #5138 + + Contributed by @Kami. + Removed ~~~~~~~~ * Removed --python3 pack install option #5100 diff --git a/st2api/tests/unit/controllers/v1/test_action_alias.py b/st2api/tests/unit/controllers/v1/test_action_alias.py index e9cdf0c52e..b507c2a161 100644 --- a/st2api/tests/unit/controllers/v1/test_action_alias.py +++ b/st2api/tests/unit/controllers/v1/test_action_alias.py @@ -24,7 +24,8 @@ FIXTURES_PACK = 'aliases' TEST_MODELS = { - 'aliases': ['alias1.yaml', 'alias2.yaml', 'alias_with_undefined_jinja_in_ack_format.yaml'] + 'aliases': ['alias1.yaml', 'alias2.yaml', 'alias_with_undefined_jinja_in_ack_format.yaml'], + 'actions': ['action1.yaml'], } TEST_LOAD_MODELS = { @@ -34,7 +35,8 @@ GENERIC_FIXTURES_PACK = 'generic' TEST_LOAD_MODELS_GENERIC = { - 'aliases': ['alias3.yaml'] + 'aliases': ['alias3.yaml'], + 'runners': ['testrunner1.yaml'] } @@ -180,6 +182,18 @@ def test_match(self): self.assertEqual(resp.json['actionalias']['name'], 'alias_with_undefined_jinja_in_ack_format') + def test_match_and_execute_success(self): + data = { + 'command': 'run whoami on localhost1', + 'source_channel': 'hubot', + 'user': "user", + } + resp = self.app.post_json("/v1/aliasexecution/match_and_execute", data) + self.assertEqual(resp.status_int, 201) + self.assertEqual(len(resp.json["results"]), 1) + self.assertTrue(resp.json["results"][0]["actionalias"]["ref"], + "aliases.alias_with_undefined_jinja_in_ack_format") + def test_help(self): resp = self.app.get("/v1/actionalias/help") self.assertEqual(resp.status_int, 200) diff --git a/st2client/st2client/commands/action_alias.py b/st2client/st2client/commands/action_alias.py index a9a15e7bed..32a65776cc 100644 --- a/st2client/st2client/commands/action_alias.py +++ b/st2client/st2client/commands/action_alias.py @@ -115,7 +115,7 @@ def __init__(self, resource, *args, **kwargs): def run(self, args, **kwargs): payload = core.Resource() payload.command = args.command_text - payload.user = args.user + payload.user = args.user or "" payload.source_channel = 'cli' alias_execution_mgr = self.app.client.managers['ActionAliasExecution'] diff --git a/st2client/st2client/models/core.py b/st2client/st2client/models/core.py index d102d3158f..255c91534f 100644 --- a/st2client/st2client/models/core.py +++ b/st2client/st2client/models/core.py @@ -373,7 +373,7 @@ def match_and_execute(self, instance, **kwargs): if response.status_code != http_client.OK: self.handle_error(response) - instance = self.resource.deserialize(response.json()) + instance = self.resource.deserialize(response.json()["results"][0]) return instance diff --git a/st2client/tests/base.py b/st2client/tests/base.py index d0e7b2253d..307f00f74b 100644 --- a/st2client/tests/base.py +++ b/st2client/tests/base.py @@ -109,6 +109,20 @@ def tearDown(self): sys.stdout = sys.__stdout__ sys.stderr = sys.__stderr__ + # On failure, we also print values of accumulated stdout and stderr + # to make troubleshooting easier + # TODO: nosetests specific make sure to update when / if switching to pytest + errors = getattr(self.__dict__.get("_outcome", None), "errors", []) + + if len(errors) >= 1: + stdout = self.stdout.getvalue() + stderr = self.stderr.getvalue() + + print("") + print("Captured stdout: %s" % (stdout)) + print("Captured stdoerr: %s" % (stderr)) + print("") + def _reset_output_streams(self): """ Reset / clear stdout and stderr stream. diff --git a/st2client/tests/unit/test_action_alias.py b/st2client/tests/unit/test_action_alias.py new file mode 100644 index 0000000000..a360fd5139 --- /dev/null +++ b/st2client/tests/unit/test_action_alias.py @@ -0,0 +1,64 @@ +# Copyright 2020 The StackStorm Authors. +# Copyright 2019 Extreme Networks, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import absolute_import + +import json +import mock + +from tests import base + +from st2client import shell +from st2client.utils import httpclient + +MOCK_MATCH_AND_EXECUTE_RESULT = { + "results": [ + { + "execution": { + "id": "mock-id", + }, + "actionalias": { + "ref": "mock-ref" + } + } + ] +} + + +class ActionAliasCommandTestCase(base.BaseCLITestCase): + def __init__(self, *args, **kwargs): + super(ActionAliasCommandTestCase, self).__init__(*args, **kwargs) + self.shell = shell.Shell() + + @mock.patch.object( + httpclient.HTTPClient, 'post', + mock.MagicMock(return_value=base.FakeResponse(json.dumps(MOCK_MATCH_AND_EXECUTE_RESULT), + 200, 'OK'))) + def test_match_and_execute(self): + ret = self.shell.run(['action-alias', 'execute', "run whoami on localhost"]) + self.assertEqual(ret, 0) + + expected_args = { + 'command': 'run whoami on localhost', + 'user': '', + 'source_channel': 'cli' + } + httpclient.HTTPClient.post.assert_called_with('/aliasexecution/match_and_execute', + expected_args) + + mock_stdout = self.stdout.getvalue() + + self.assertTrue("Matching Action-alias: 'mock-ref'" in mock_stdout) + self.assertTrue("st2 execution get mock-id" in mock_stdout) diff --git a/st2tests/st2tests/fixtures/aliases/actions/action1.yaml b/st2tests/st2tests/fixtures/aliases/actions/action1.yaml index c9be03ce3d..7a0d9c7bdf 100644 --- a/st2tests/st2tests/fixtures/aliases/actions/action1.yaml +++ b/st2tests/st2tests/fixtures/aliases/actions/action1.yaml @@ -1,7 +1,7 @@ --- name: "action1" description: "" - runner_type: "test-runner" + runner_type: "noop" pack: "wolfpack" entry_point: "/tmp/test/action1.sh" enabled: true @@ -15,3 +15,7 @@ param4: type: "string" secret: true + hosts: + type: "string" + cmd: + type: "string"