From 65775eade77791fffa14ed7272a896e61ed69672 Mon Sep 17 00:00:00 2001 From: Eduardo Dobay Date: Fri, 15 May 2020 00:00:39 -0300 Subject: [PATCH] Unique rule names for multiple CloudWatch expressions (#1727) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A mixture of two cases that were handled individually uncovers an incorrect behavior: when a function has multiple event expressions AND the resulting rule name would be >= 64 characters long, all expressions get the same hash, so only the last expression is scheduled. In this commit, the index of the expression is used to build the hash, but only if the index is not zero — this is possibly not needed, but ensures current hashes are preserved. --- tests/tests.py | 20 +++++++++++++++++--- zappa/core.py | 19 +++++++++++++------ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/tests/tests.py b/tests/tests.py index 52c3a6eb7..12e1b5480 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -2033,16 +2033,30 @@ def test_hashed_rule_name(self): ) self.assertTrue(len(truncated) == 64) - rule_name = zappa.get_hashed_rule_name( + rule_name_index0 = zappa.get_hashed_rule_name( event=dict(name="some-event-name"), function="this.is.my.dang.function.wassup.yeah.its.long", lambda_name="basldfkjalsdkfjalsdkfjaslkdfjalsdkfjadlsfkjasdlfkjasdlfkjasdflkjasdf-asdfasdfasdfasdfasdf", + index=0, ) - self.assertTrue(len(rule_name) <= 64) + self.assertTrue(len(rule_name_index0) <= 64) self.assertTrue( - rule_name.endswith("-this.is.my.dang.function.wassup.yeah.its.long") + rule_name_index0.endswith("-this.is.my.dang.function.wassup.yeah.its.long") ) + rule_name_index1 = zappa.get_hashed_rule_name( + event=dict(name="some-event-name"), + function="this.is.my.dang.function.wassup.yeah.its.long", + lambda_name="basldfkjalsdkfjalsdkfjaslkdfjalsdkfjadlsfkjasdlfkjasdlfkjasdflkjasdf-asdfasdfasdfasdfasdf", + index=1, + ) + self.assertTrue(len(rule_name_index1) <= 64) + self.assertTrue( + rule_name_index1.endswith("-this.is.my.dang.function.wassup.yeah.its.long") + ) + + self.assertNotEqual(rule_name_index0, rule_name_index1) + def test_detect_dj(self): # Sanity settings_modules = detect_django_settings() diff --git a/zappa/core.py b/zappa/core.py index 19d76b682..858c0d909 100644 --- a/zappa/core.py +++ b/zappa/core.py @@ -3045,7 +3045,7 @@ def schedule_events(self, lambda_arn, lambda_name, events, default=True): # https://github.com/Miserlou/Zappa/issues/970 if len(name) >= 64: rule_name = self.get_hashed_rule_name( - event, function, lambda_name + event, function, lambda_name, index ) else: rule_name = name @@ -3194,15 +3194,22 @@ def get_event_name(lambda_name, name): )[:64] @staticmethod - def get_hashed_rule_name(event, function, lambda_name): + def get_hashed_rule_name(event, function, lambda_name, index=0): """ - Returns an AWS-valid CloudWatch rule name using a digest of the event name, lambda name, and function. + Returns an AWS-valid CloudWatch rule name using a digest of the event name, lambda name, function, + and an index in the case of multiple scheduling expressions. + This allows support for rule names that may be longer than the 64 char limit. """ event_name = event.get("name", function) - name_hash = hashlib.sha1( - "{}-{}".format(lambda_name, event_name).encode("UTF-8") - ).hexdigest() + name = "{}-{}".format(lambda_name, event_name) + + # Similarly to get_scheduled_event_name, we need unique rule names in case of multiple expressions. + # Related: https://github.com/Miserlou/Zappa/issues/1727 + if index: + name = "{}-{}".format(name, index) + + name_hash = hashlib.sha1(name.encode("UTF-8")).hexdigest() return Zappa.get_event_name(name_hash, function) def delete_rule(self, rule_name):