diff --git a/.changes/next-release/bugfix-Waiter-88466.json b/.changes/next-release/bugfix-Waiter-88466.json new file mode 100644 index 0000000000..35e969b4cb --- /dev/null +++ b/.changes/next-release/bugfix-Waiter-88466.json @@ -0,0 +1,5 @@ +{ + "type": "bugfix", + "category": "Waiter", + "description": "Update waiters to handle expected boolean values when matching errors (`boto/botocore#3220 `__)" +} diff --git a/botocore/waiter.py b/botocore/waiter.py index 2362eebeda..47f71886d4 100644 --- a/botocore/waiter.py +++ b/botocore/waiter.py @@ -302,7 +302,15 @@ def acceptor_matches(response): # response. So response is still a dictionary, and in the case # of an error response will contain the "Error" and # "ResponseMetadata" key. - return response.get("Error", {}).get("Code", "") == expected + # When expected is True, accept any error code. + # When expected is False, check if any errors were encountered. + # Otherwise, check for a specific AWS error code. + if expected is True: + return "Error" in response and "Code" in response["Error"] + elif expected is False: + return "Error" not in response + else: + return response.get("Error", {}).get("Code", "") == expected return acceptor_matches diff --git a/tests/unit/test_waiters.py b/tests/unit/test_waiters.py index 62544e180a..7ec9b23e5c 100644 --- a/tests/unit/test_waiters.py +++ b/tests/unit/test_waiters.py @@ -189,6 +189,38 @@ def test_single_waiter_supports_error(self): success_acceptor({'Error': {'Code': 'DoesNotExistErorr'}}) ) + def test_single_waiter_supports_no_error(self): + single_waiter = { + 'acceptors': [ + { + 'state': 'success', + 'matcher': 'error', + 'expected': False, + } + ], + } + single_waiter.update(self.boiler_plate_config) + config = SingleWaiterConfig(single_waiter) + success_acceptor = config.acceptors[0].matcher_func + self.assertTrue(success_acceptor({})) + self.assertFalse(success_acceptor({'Error': {'Code': 'ExampleError'}})) + + def test_single_waiter_supports_any_error(self): + single_waiter = { + 'acceptors': [ + { + 'state': 'success', + 'matcher': 'error', + 'expected': True, + } + ], + } + single_waiter.update(self.boiler_plate_config) + config = SingleWaiterConfig(single_waiter) + success_acceptor = config.acceptors[0].matcher_func + self.assertTrue(success_acceptor({'Error': {'Code': 'ExampleError1'}})) + self.assertTrue(success_acceptor({'Error': {'Code': 'ExampleError2'}})) + def test_unknown_matcher(self): unknown_type = 'arbitrary_type' single_waiter = {