diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9861e0a09d..5cbba13f17 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -9,6 +9,8 @@ in development * Add support for caching of the retrieved auth tokens to the CLI. (new-feature) * Throw a more-user friendly exception when enforcing a rule if an action referenced inside the rule definition doesn't exist. (improvement) +* Fix a bug with the rule evaluation failing if the trigger payload contained a key with a + dot in the name. (bug-fix) v0.9.0 - April 29, 2015 ----------------------- diff --git a/Makefile b/Makefile index 1d85a120f4..7892126c8f 100644 --- a/Makefile +++ b/Makefile @@ -90,7 +90,7 @@ pylint: requirements .pylint echo "==========================================================="; \ echo "Running pylint on" $$component; \ echo "==========================================================="; \ - . $(VIRTUALENV_DIR)/bin/activate; pylint -E --rcfile=./.pylintrc --load-plugins=pylint_plugins.api_models $$component/$$component; \ + . $(VIRTUALENV_DIR)/bin/activate; pylint -E --rcfile=./.pylintrc --load-plugins=pylint_plugins.api_models $$component/$$component || exit 1; \ done .PHONY: flake8 diff --git a/st2actions/st2actions/resultstracker.py b/st2actions/st2actions/resultstracker.py index 1bb5d9060f..6159a50389 100644 --- a/st2actions/st2actions/resultstracker.py +++ b/st2actions/st2actions/resultstracker.py @@ -49,7 +49,7 @@ def start(self, wait=False): def wait(self): super(ResultsTracker, self).wait() - for thread in self._query_threads(): + for thread in self._query_threads: thread.wait() def shutdown(self): diff --git a/st2common/st2common/models/db/reactor.py b/st2common/st2common/models/db/reactor.py index 61397e1d68..0466bce68c 100644 --- a/st2common/st2common/models/db/reactor.py +++ b/st2common/st2common/models/db/reactor.py @@ -91,7 +91,7 @@ class TriggerInstanceDB(stormbase.StormFoundationDB): occurrence_time (datetime): time of occurrence of the trigger. """ trigger = me.StringField() - payload = me.DictField() + payload = stormbase.EscapedDictField() occurrence_time = me.DateTimeField() diff --git a/st2reactor/tests/unit/test_rule_matcher.py b/st2reactor/tests/unit/test_rule_matcher.py index 8b527d46ee..a7347b29cd 100644 --- a/st2reactor/tests/unit/test_rule_matcher.py +++ b/st2reactor/tests/unit/test_rule_matcher.py @@ -25,6 +25,7 @@ class RuleMatcherTest(DbTestCase): + rules = [] def test_get_matching_rules(self): self._setup_sample_trigger('st2.test.trigger1') @@ -40,6 +41,22 @@ def test_get_matching_rules(self): self.assertTrue(matching_rules is not None) self.assertEqual(len(matching_rules), 1) + def test_trigger_instance_payload_with_special_values(self): + # Test a rule where TriggerInstance payload contains a dot (".") and $ + self._setup_sample_trigger('st2.test.trigger2') + trigger_instance = container_utils.create_trigger_instance( + 'dummy_pack_1.st2.test.trigger2', + {'k1': 't1_p_v', 'k2.k2': 'v2', 'k3.more.nested.deep': 'some.value', + 'k4.even.more.nested$': 'foo', 'yep$aaa': 'b'}, + datetime.datetime.utcnow() + ) + trigger = get_trigger_db_by_ref(trigger_instance.trigger) + rules = self._get_sample_rules() + rules_matcher = RulesMatcher(trigger_instance, trigger, rules) + matching_rules = rules_matcher.get_matching_rules() + self.assertTrue(matching_rules is not None) + self.assertEqual(len(matching_rules), 1) + def _setup_sample_trigger(self, name): trigtype = TriggerTypeDB() trigtype.name = name @@ -58,7 +75,9 @@ def _setup_sample_trigger(self, name): Trigger.add_or_update(created) def _get_sample_rules(self): - rules = [] + if self.rules: + # Make sure rules are created only once + return self.rules RULE_1 = { 'enabled': True, @@ -85,7 +104,7 @@ def _get_sample_rules(self): rule_api = RuleAPI(**RULE_1) rule_db = RuleAPI.to_model(rule_api) rule_db = Rule.add_or_update(rule_db) - rules.append(rule_db) + self.rules.append(rule_db) RULE_2 = { # Rule should match. 'enabled': True, @@ -112,7 +131,7 @@ def _get_sample_rules(self): rule_api = RuleAPI(**RULE_2) rule_db = RuleAPI.to_model(rule_api) rule_db = Rule.add_or_update(rule_db) - rules.append(rule_db) + self.rules.append(rule_db) RULE_3 = { 'enabled': False, # Disabled rule shouldn't match. @@ -139,6 +158,6 @@ def _get_sample_rules(self): rule_api = RuleAPI(**RULE_3) rule_db = RuleAPI.to_model(rule_api) rule_db = Rule.add_or_update(rule_db) - rules.append(rule_db) + self.rules.append(rule_db) - return rules + return self.rules