From 77ebaac6432d6b1f02f26e55897547a4e0ee56f9 Mon Sep 17 00:00:00 2001 From: amanda Date: Thu, 12 Aug 2021 18:08:45 +0100 Subject: [PATCH 01/10] Initial fix, that on local testing resolves issue --- .../st2api/controllers/v1/actionexecutions.py | 2 ++ st2common/st2common/services/action.py | 17 +++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/st2api/st2api/controllers/v1/actionexecutions.py b/st2api/st2api/controllers/v1/actionexecutions.py index cc20c61f52..1128121edd 100644 --- a/st2api/st2api/controllers/v1/actionexecutions.py +++ b/st2api/st2api/controllers/v1/actionexecutions.py @@ -150,6 +150,7 @@ def _handle_schedule_execution( abort(http_client.BAD_REQUEST, six.text_type(e)) except jsonschema.ValidationError as e: LOG.exception("Unable to execute action. Parameter validation failed.") + LOG.error(e, exc_info=True) abort( http_client.BAD_REQUEST, re.sub("u'([^']*)'", r"'\1'", getattr(e, "message", six.text_type(e))), @@ -219,6 +220,7 @@ def _schedule_execution( liveaction=liveaction_db, action_db=action_db, runnertype_db=runnertype_db, + validate_params=False, ) # By this point the execution is already in the DB therefore need to mark it failed. diff --git a/st2common/st2common/services/action.py b/st2common/st2common/services/action.py index b7bf650bde..fc125c0f91 100644 --- a/st2common/st2common/services/action.py +++ b/st2common/st2common/services/action.py @@ -55,7 +55,7 @@ def _get_immutable_params(parameters): return [k for k, v in six.iteritems(parameters) if v.get("immutable", False)] -def create_request(liveaction, action_db=None, runnertype_db=None): +def create_request(liveaction, action_db=None, runnertype_db=None, validate_params=True): """ Create an action execution. @@ -108,13 +108,14 @@ def create_request(liveaction, action_db=None, runnertype_db=None): # Validate action parameters. schema = util_schema.get_schema_for_action_parameters(action_db, runnertype_db) validator = util_schema.get_validator() - util_schema.validate( - liveaction.parameters, - schema, - validator, - use_default=True, - allow_default_none=True, - ) + if validate_params: + util_schema.validate( + liveaction.parameters, + schema, + validator, + use_default=True, + allow_default_none=True, + ) # validate that no immutable params are being overriden. Although possible to # ignore the override it is safer to inform the user to avoid surprises. From de1a1832491fdbd3654cd6bf41fd905220813fde Mon Sep 17 00:00:00 2001 From: Amanda McGuinness Date: Fri, 13 Aug 2021 15:15:55 +0000 Subject: [PATCH 02/10] Add unit-tests --- .../unit/controllers/v1/test_executions.py | 50 +++++++++++++++++++ st2common/tests/unit/services/test_action.py | 28 +++++++++++ 2 files changed, 78 insertions(+) diff --git a/st2api/tests/unit/controllers/v1/test_executions.py b/st2api/tests/unit/controllers/v1/test_executions.py index 5afcdbaeda..6dcd1a7ffc 100644 --- a/st2api/tests/unit/controllers/v1/test_executions.py +++ b/st2api/tests/unit/controllers/v1/test_executions.py @@ -28,6 +28,8 @@ from st2common.constants.secrets import MASKED_ATTRIBUTE_VALUE from st2common.constants.keyvalue import FULL_USER_SCOPE from st2common.content import utils as content_utils +from st2common.exceptions.param import ParamException +from st2common.exceptions.apivalidation import ValueValidationException from st2common.models.api.keyvalue import KeyValuePairAPI from st2common.models.db.auth import UserDB from st2common.models.db.execution import ActionExecutionDB @@ -198,6 +200,26 @@ "non_secret_param_2": {"type": "string", "required": True}, }, } +ACTION_DEFAULT_ENCRYPT_AND_BOOL = { + "name": "st2.dummy.default_encrypted_and_bool", + "description": "An action that uses a jinja template with decrypt_kv filter " + "in default parameter", + "enabled": True, + "pack": "starterpack", + "runner_type": "local-shell-cmd", + "parameters": { + "encrypted_param": { + "type": "string", + "default": "{{ st2kv.system.secret | decrypt_kv }}", + "secret": True, + }, + "bool_param": { + "type": "boolean", + "default": "{{ st2kv.system.test_bool }}", + }, + }, +} + LIVE_ACTION_1 = { "action": "sixpack.st2.dummy.action1", @@ -298,6 +320,9 @@ LIVE_ACTION_DEFAULT_ENCRYPT = { "action": "starterpack.st2.dummy.default_encrypted_value", } +LIVE_ACTION_DEFAULT_ENCRYPT_AND_BOOL = { + "action": "starterpack.st2.dummy.default_encrypted_and_bool", +} LIVE_ACTION_DEFAULT_ENCRYPT_SECRET_PARAM = { "action": "starterpack.st2.dummy.default_encrypted_value_secret_param", } @@ -359,6 +384,10 @@ def setUpClass(cls): post_resp = cls.app.post_json("/v1/actions", cls.action_decrypt) cls.action_decrypt["id"] = post_resp.json["id"] + cls.action_decrypt_and_bool = copy.deepcopy(ACTION_DEFAULT_ENCRYPT_AND_BOOL) + post_resp = cls.app.post_json("/v1/actions", cls.action_decrypt_and_bool) + cls.action_decrypt_and_bool["id"] = post_resp.json["id"] + cls.action_decrypt_secret_param = copy.deepcopy( ACTION_DEFAULT_ENCRYPT_SECRET_PARAMS ) @@ -390,6 +419,8 @@ def tearDownClass(cls): cls.app.delete("/v1/actions/%s" % cls.action_inquiry["id"]) cls.app.delete("/v1/actions/%s" % cls.action_template["id"]) cls.app.delete("/v1/actions/%s" % cls.action_decrypt["id"]) + cls.app.delete("/v1/actions/%s" % cls.action_decrypt_secret_param["id"]) + cls.app.delete("/v1/actions/%s" % cls.action_decrypt_and_bool["id"]) cls.app.delete( "/v1/actions/%s" % cls.action_with_output_schema_secret_param["id"] ) @@ -913,6 +944,24 @@ def test_template_param(self): # was not rendered, and the provided parameter was used self.assertEqual(post_resp.json["parameters"]["intparam"], live_int_param) + def test_template_encrypted_and_bool(self): + # register datastore values which are used in this test case + KeyValuePairAPI._setup_crypto() + register_items = [ + { + "name": "test_bool", + "value": "true", + }, + ] + kvps = [KeyValuePair.add_or_update(KeyValuePairDB(**x)) for x in register_items] + + post_resp = self._do_post(LIVE_ACTION_DEFAULT_ENCRYPT_AND_BOOL, expect_errors=True) + self.assertEqual(post_resp.status_int, 400) + self.assertEqual(post_resp.json["faultstring"], + 'Failed to render parameter "encrypted_param": Referenced datastore item "st2kv.system.secret" doesn\'t exist or it contains an empty string' + ) + + def test_template_encrypted_params(self): # register datastore values which are used in this test case KeyValuePairAPI._setup_crypto() @@ -2071,3 +2120,4 @@ def test_get_output_finished_execution(self): self.assertEqual(resp.status_int, 200) lines = resp.text.strip().split("\n") self.assertEqual(len(lines), 10) + diff --git a/st2common/tests/unit/services/test_action.py b/st2common/tests/unit/services/test_action.py index ab8db72329..4f1ea811e3 100644 --- a/st2common/tests/unit/services/test_action.py +++ b/st2common/tests/unit/services/test_action.py @@ -624,3 +624,31 @@ def test_root_liveaction(self): child, expected_root = self._create_nested_executions(depth=i) actual_root = action_service.get_root_liveaction(child) self.assertEqual(expected_root["id"], actual_root["id"]) + + def test_req_invalid_parameters(self): + parameters = {"hosts": "127.0.0.1", "cmd": "uname -a", "arg_default_value": 123} + liveaction = LiveActionDB(action=ACTION_REF, parameters=parameters) + self.assertRaises( + jsonschema.ValidationError, action_service.request, liveaction + ) + + def test_invalid_json_request_validate(self): + parameters = {"hosts": "127.0.0.1", "cmd": "uname -a", "arg_default_value": 123} + liveaction = LiveActionDB(action=ACTION_REF, parameters=parameters) + + self.assertRaises( + jsonschema.ValidationError, + action_service.create_request, + liveaction, + ) + + def test_invalid_json_request_skipvalidate(self): + parameters = {"hosts": "127.0.0.1", "cmd": "uname -a", "arg_default_value": 123} + liveaction = LiveActionDB(action=ACTION_REF, parameters=parameters) + + self.assertRaises( + jsonschema.ValidationError, + action_service.create_request, + liveaction, + False, + ) From 224b9435b6637b40332327fa562b3125c92ceb9d Mon Sep 17 00:00:00 2001 From: Amanda McGuinness Date: Fri, 13 Aug 2021 15:26:06 +0000 Subject: [PATCH 03/10] Add changelog and fix black errors --- CHANGELOG.rst | 7 ++++ .../tests/unit/controllers/v1/test_actions.py | 33 +++++++++++++++++++ .../unit/controllers/v1/test_executions.py | 11 ++++--- st2common/st2common/services/action.py | 4 ++- 4 files changed, 49 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c5421460ef..c0515670a8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -20,6 +20,13 @@ Changed Contributed by @ericreeves. +Fixed +~~~~~ + +* Correct error reported when encrypted key value is reported, and another key value parameter that requires conversion is present. #5328 + Contributed by @amanda11, Ammeon Solutions + + 3.5.0 - June 23, 2021 --------------------- diff --git a/st2api/tests/unit/controllers/v1/test_actions.py b/st2api/tests/unit/controllers/v1/test_actions.py index cd1d8b555c..bb53480488 100644 --- a/st2api/tests/unit/controllers/v1/test_actions.py +++ b/st2api/tests/unit/controllers/v1/test_actions.py @@ -293,6 +293,22 @@ "notify": {"on-complete": {"message": "Woohoo! I completed!!!"}}, } +ACTION_KV_ERRORS = { + "name": "st2.dummy.action_kv", + "description": "test description", + "enabled": True, + "pack": "wolfpack", + "entry_point": "/tmp/test/action1.sh", + "runner_type": "local-shell-script", + "parameters": { + "a": { + "type": "string", + "default": "{{ st2kv.system.test_encrypt | decrypt_kv }}", + }, + "b": {"type": "boolean", "default": "{{ st2kv.system.test_bool }}"}, + }, +} + class ActionsControllerTestCase( FunctionalTest, APIControllerWithIncludeAndExcludeFilterTestCase, CleanFilesTestCase @@ -308,6 +324,12 @@ class ActionsControllerTestCase( os.path.join(get_fixtures_packs_base_path(), "dummy_pack_1/actions/filea.txt") ] + def setUp(self): + # Delete any actions in case of previous failed runs + resp = self.app.get("/v1/actions") + for i in resp.json: + self.__do_delete(i["id"]) + @mock.patch.object( action_validator, "validate_action", mock.MagicMock(return_value=True) ) @@ -740,6 +762,17 @@ def test_get_one_using_tag_parameter(self): self.assertEqual(get_resp.json[0]["tags"], action_tags) self.__do_delete(action_id) + # @mock.patch.object( + # action_validator, "validate_action", mock.MagicMock(return_value=True) + # ) + def test_action_with_kv_failure(self): + post_resp = self.__do_post(ACTION_KV_ERRORS) + action_id = self.__get_action_id(post_resp) + get_resp = self.__do_get_one(action_id) + self.assertEqual(get_resp.status_int, 200) + self.assertEqual(self.__get_action_id(get_resp), action_id) + self.__do_delete(action_id) + # TODO: Re-enable those tests after we ensure DB is flushed in setUp # and each test starts in a clean state diff --git a/st2api/tests/unit/controllers/v1/test_executions.py b/st2api/tests/unit/controllers/v1/test_executions.py index 6dcd1a7ffc..f2c4675623 100644 --- a/st2api/tests/unit/controllers/v1/test_executions.py +++ b/st2api/tests/unit/controllers/v1/test_executions.py @@ -955,13 +955,15 @@ def test_template_encrypted_and_bool(self): ] kvps = [KeyValuePair.add_or_update(KeyValuePairDB(**x)) for x in register_items] - post_resp = self._do_post(LIVE_ACTION_DEFAULT_ENCRYPT_AND_BOOL, expect_errors=True) + post_resp = self._do_post( + LIVE_ACTION_DEFAULT_ENCRYPT_AND_BOOL, expect_errors=True + ) self.assertEqual(post_resp.status_int, 400) - self.assertEqual(post_resp.json["faultstring"], - 'Failed to render parameter "encrypted_param": Referenced datastore item "st2kv.system.secret" doesn\'t exist or it contains an empty string' + self.assertEqual( + post_resp.json["faultstring"], + 'Failed to render parameter "encrypted_param": Referenced datastore item "st2kv.system.secret" doesn\'t exist or it contains an empty string', ) - def test_template_encrypted_params(self): # register datastore values which are used in this test case KeyValuePairAPI._setup_crypto() @@ -2120,4 +2122,3 @@ def test_get_output_finished_execution(self): self.assertEqual(resp.status_int, 200) lines = resp.text.strip().split("\n") self.assertEqual(len(lines), 10) - diff --git a/st2common/st2common/services/action.py b/st2common/st2common/services/action.py index fc125c0f91..d0bebcfcc7 100644 --- a/st2common/st2common/services/action.py +++ b/st2common/st2common/services/action.py @@ -55,7 +55,9 @@ def _get_immutable_params(parameters): return [k for k, v in six.iteritems(parameters) if v.get("immutable", False)] -def create_request(liveaction, action_db=None, runnertype_db=None, validate_params=True): +def create_request( + liveaction, action_db=None, runnertype_db=None, validate_params=True +): """ Create an action execution. From 2a4cfaf7a85864b9fa2c1755194d0a7566abdaab Mon Sep 17 00:00:00 2001 From: Amanda McGuinness Date: Fri, 13 Aug 2021 15:29:48 +0000 Subject: [PATCH 04/10] Unexpected test file change included --- .../tests/unit/controllers/v1/test_actions.py | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/st2api/tests/unit/controllers/v1/test_actions.py b/st2api/tests/unit/controllers/v1/test_actions.py index bb53480488..cd1d8b555c 100644 --- a/st2api/tests/unit/controllers/v1/test_actions.py +++ b/st2api/tests/unit/controllers/v1/test_actions.py @@ -293,22 +293,6 @@ "notify": {"on-complete": {"message": "Woohoo! I completed!!!"}}, } -ACTION_KV_ERRORS = { - "name": "st2.dummy.action_kv", - "description": "test description", - "enabled": True, - "pack": "wolfpack", - "entry_point": "/tmp/test/action1.sh", - "runner_type": "local-shell-script", - "parameters": { - "a": { - "type": "string", - "default": "{{ st2kv.system.test_encrypt | decrypt_kv }}", - }, - "b": {"type": "boolean", "default": "{{ st2kv.system.test_bool }}"}, - }, -} - class ActionsControllerTestCase( FunctionalTest, APIControllerWithIncludeAndExcludeFilterTestCase, CleanFilesTestCase @@ -324,12 +308,6 @@ class ActionsControllerTestCase( os.path.join(get_fixtures_packs_base_path(), "dummy_pack_1/actions/filea.txt") ] - def setUp(self): - # Delete any actions in case of previous failed runs - resp = self.app.get("/v1/actions") - for i in resp.json: - self.__do_delete(i["id"]) - @mock.patch.object( action_validator, "validate_action", mock.MagicMock(return_value=True) ) @@ -762,17 +740,6 @@ def test_get_one_using_tag_parameter(self): self.assertEqual(get_resp.json[0]["tags"], action_tags) self.__do_delete(action_id) - # @mock.patch.object( - # action_validator, "validate_action", mock.MagicMock(return_value=True) - # ) - def test_action_with_kv_failure(self): - post_resp = self.__do_post(ACTION_KV_ERRORS) - action_id = self.__get_action_id(post_resp) - get_resp = self.__do_get_one(action_id) - self.assertEqual(get_resp.status_int, 200) - self.assertEqual(self.__get_action_id(get_resp), action_id) - self.__do_delete(action_id) - # TODO: Re-enable those tests after we ensure DB is flushed in setUp # and each test starts in a clean state From 439b1f479bf2cc77fcede876c51dab124b9520a4 Mon Sep 17 00:00:00 2001 From: Amanda McGuinness Date: Fri, 13 Aug 2021 15:32:02 +0000 Subject: [PATCH 05/10] Remove code added for debugging --- st2api/st2api/controllers/v1/actionexecutions.py | 1 - st2api/tests/unit/controllers/v1/test_executions.py | 2 -- 2 files changed, 3 deletions(-) diff --git a/st2api/st2api/controllers/v1/actionexecutions.py b/st2api/st2api/controllers/v1/actionexecutions.py index 1128121edd..70d709192e 100644 --- a/st2api/st2api/controllers/v1/actionexecutions.py +++ b/st2api/st2api/controllers/v1/actionexecutions.py @@ -150,7 +150,6 @@ def _handle_schedule_execution( abort(http_client.BAD_REQUEST, six.text_type(e)) except jsonschema.ValidationError as e: LOG.exception("Unable to execute action. Parameter validation failed.") - LOG.error(e, exc_info=True) abort( http_client.BAD_REQUEST, re.sub("u'([^']*)'", r"'\1'", getattr(e, "message", six.text_type(e))), diff --git a/st2api/tests/unit/controllers/v1/test_executions.py b/st2api/tests/unit/controllers/v1/test_executions.py index f2c4675623..dddc325b45 100644 --- a/st2api/tests/unit/controllers/v1/test_executions.py +++ b/st2api/tests/unit/controllers/v1/test_executions.py @@ -28,8 +28,6 @@ from st2common.constants.secrets import MASKED_ATTRIBUTE_VALUE from st2common.constants.keyvalue import FULL_USER_SCOPE from st2common.content import utils as content_utils -from st2common.exceptions.param import ParamException -from st2common.exceptions.apivalidation import ValueValidationException from st2common.models.api.keyvalue import KeyValuePairAPI from st2common.models.db.auth import UserDB from st2common.models.db.execution import ActionExecutionDB From 5a955a97f773f1448e2b5ee94f641b37418c7b5e Mon Sep 17 00:00:00 2001 From: Amanda McGuinness Date: Fri, 13 Aug 2021 15:45:15 +0000 Subject: [PATCH 06/10] Fix flake8 errors --- st2common/tests/unit/services/test_action.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/st2common/tests/unit/services/test_action.py b/st2common/tests/unit/services/test_action.py index 4f1ea811e3..d9b0e6d0f8 100644 --- a/st2common/tests/unit/services/test_action.py +++ b/st2common/tests/unit/services/test_action.py @@ -625,13 +625,6 @@ def test_root_liveaction(self): actual_root = action_service.get_root_liveaction(child) self.assertEqual(expected_root["id"], actual_root["id"]) - def test_req_invalid_parameters(self): - parameters = {"hosts": "127.0.0.1", "cmd": "uname -a", "arg_default_value": 123} - liveaction = LiveActionDB(action=ACTION_REF, parameters=parameters) - self.assertRaises( - jsonschema.ValidationError, action_service.request, liveaction - ) - def test_invalid_json_request_validate(self): parameters = {"hosts": "127.0.0.1", "cmd": "uname -a", "arg_default_value": 123} liveaction = LiveActionDB(action=ACTION_REF, parameters=parameters) From 1856d1a2cb6a5dfc8b84baa3b200ee1fffa36baa Mon Sep 17 00:00:00 2001 From: Amanda McGuinness Date: Fri, 13 Aug 2021 15:49:36 +0000 Subject: [PATCH 07/10] Add missing test change for flake8 --- st2api/tests/unit/controllers/v1/test_executions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/st2api/tests/unit/controllers/v1/test_executions.py b/st2api/tests/unit/controllers/v1/test_executions.py index dddc325b45..fb80a35917 100644 --- a/st2api/tests/unit/controllers/v1/test_executions.py +++ b/st2api/tests/unit/controllers/v1/test_executions.py @@ -951,7 +951,7 @@ def test_template_encrypted_and_bool(self): "value": "true", }, ] - kvps = [KeyValuePair.add_or_update(KeyValuePairDB(**x)) for x in register_items] + [KeyValuePair.add_or_update(KeyValuePairDB(**x)) for x in register_items] post_resp = self._do_post( LIVE_ACTION_DEFAULT_ENCRYPT_AND_BOOL, expect_errors=True From 9915691ebf775c86371049ab3af114bdea123583 Mon Sep 17 00:00:00 2001 From: Amanda McGuinness Date: Mon, 6 Sep 2021 09:44:47 +0000 Subject: [PATCH 08/10] Address review comments and fix UT --- st2common/st2common/services/action.py | 3 +++ st2common/tests/unit/services/test_action.py | 13 ++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/st2common/st2common/services/action.py b/st2common/st2common/services/action.py index d0bebcfcc7..cb5c9ebbe6 100644 --- a/st2common/st2common/services/action.py +++ b/st2common/st2common/services/action.py @@ -68,6 +68,9 @@ def create_request( :param runnertype_db: Runner model to operate one. If not provided, one is retrieved from the database using values from "liveaction". :type runnertype_db: :class:`RunnerTypeDB` + :param validate_params: Whether to validate parameters against schema. Default to True, but + set to False when raising a request to report an error. + :type validate_params: ``bool`` :return: (liveaction, execution) :rtype: tuple diff --git a/st2common/tests/unit/services/test_action.py b/st2common/tests/unit/services/test_action.py index d9b0e6d0f8..b85b0d685d 100644 --- a/st2common/tests/unit/services/test_action.py +++ b/st2common/tests/unit/services/test_action.py @@ -629,8 +629,9 @@ def test_invalid_json_request_validate(self): parameters = {"hosts": "127.0.0.1", "cmd": "uname -a", "arg_default_value": 123} liveaction = LiveActionDB(action=ACTION_REF, parameters=parameters) - self.assertRaises( + self.assertRaisesRegexp( jsonschema.ValidationError, + "123 is not of type 'string'", action_service.create_request, liveaction, ) @@ -639,9 +640,7 @@ def test_invalid_json_request_skipvalidate(self): parameters = {"hosts": "127.0.0.1", "cmd": "uname -a", "arg_default_value": 123} liveaction = LiveActionDB(action=ACTION_REF, parameters=parameters) - self.assertRaises( - jsonschema.ValidationError, - action_service.create_request, - liveaction, - False, - ) + # Validate that if skip validation that no exception raised + (action, execution) = action_service.create_request(liveaction, validate_params = False) + self.assertTrue(action) + self.assertTrue(execution) From b0b261f06ad2b93b8d156daf30044f073906e4ba Mon Sep 17 00:00:00 2001 From: Amanda McGuinness Date: Mon, 6 Sep 2021 10:45:53 +0000 Subject: [PATCH 09/10] Fix black check --- st2common/tests/unit/services/test_action.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/st2common/tests/unit/services/test_action.py b/st2common/tests/unit/services/test_action.py index b85b0d685d..e27126ec86 100644 --- a/st2common/tests/unit/services/test_action.py +++ b/st2common/tests/unit/services/test_action.py @@ -641,6 +641,8 @@ def test_invalid_json_request_skipvalidate(self): liveaction = LiveActionDB(action=ACTION_REF, parameters=parameters) # Validate that if skip validation that no exception raised - (action, execution) = action_service.create_request(liveaction, validate_params = False) + (action, execution) = action_service.create_request( + liveaction, validate_params=False + ) self.assertTrue(action) self.assertTrue(execution) From 795fcdda5ef61853c21dda84623be464b3e5bac3 Mon Sep 17 00:00:00 2001 From: Amanda McGuinness Date: Mon, 6 Sep 2021 12:15:06 +0000 Subject: [PATCH 10/10] Remove trailing space on changelog --- CHANGELOG.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 77980ed772..63f25ef12a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -28,7 +28,7 @@ Changed * Reduced minimum TTL on garbage collection for action executions and trigger instances from 7 days to 1 day. #5287 Contributed by @ericreeves. - + * update db connect mongo connection test - `isMaster` MongoDB command depreciated, switch to `ping` #5302, #5341 Contributed by @lukepatrick