@@ -273,7 +273,7 @@ def test_check_enforcements_no_execution(self):
273273 enforced_at = '2018-10-26T01:00:00.01Z' ,
274274 rule = {'ref' : 'test_rule' })
275275 mock_rule_enforcement = mock .Mock (id = "test_id" ,
276- failure_reason = "test_failure" )
276+ failure_reason = "test_failure" )
277277
278278 mock_st2_client = mock .MagicMock ()
279279 mock_st2_client .ruleenforcements .get_by_id .return_value = mock_rule_enforcement
@@ -309,7 +309,7 @@ def test_check_enforcements_no_execution_jinja_escaping(self):
309309 enforced_at = '2018-10-26T01:00:00.01Z' ,
310310 rule = {'ref' : 'test_rule' })
311311 mock_rule_enforcement = mock .Mock (id = "test_id" ,
312- failure_reason = '{{ test_failure }}' )
312+ failure_reason = '{{ test_failure }}' )
313313
314314 mock_st2_client = mock .MagicMock ()
315315 mock_st2_client .ruleenforcements .get_by_id .return_value = mock_rule_enforcement
@@ -341,8 +341,8 @@ def test_check_enforcements_true(self):
341341 sensor .kv_enforcements = {}
342342
343343 mock_enforcement = mock .Mock (enforced_at = '2018-10-26T01:00:00.01Z' ,
344- execution_id = 'test' ,
345- rule = {'ref' : 'test_rule' })
344+ execution_id = 'test' ,
345+ rule = {'ref' : 'test_rule' })
346346 mock_execution = mock .Mock (status = 'succeeded' )
347347
348348 mock_st2_client = mock .MagicMock ()
@@ -487,3 +487,119 @@ def test_convert_to_crontab_day_convert(self):
487487 expected_return = '* * * * * 4 *'
488488 result_value = sensor .convert_to_crontab (test_dict )
489489 self .assertEqual (result_value , expected_return )
490+
491+ # Enhanced functionality tests
492+ def test_migrate_kv_format_old_to_new (self ):
493+ sensor = self .get_sensor_instance ()
494+ old_format = {
495+ 'rule1' : 'enforcement_id_1' ,
496+ 'rule2' : 'error without enforcement id'
497+ }
498+
499+ result = sensor ._migrate_kv_format (old_format )
500+
501+ expected = {
502+ 'rule1' : {'enforcement_id' : 'enforcement_id_1' , 'previous_state' : 'unknown' },
503+ 'rule2' : {'enforcement_id' : 'error without enforcement id' , 'previous_state' : 'unknown' }
504+ }
505+ self .assertEqual (result , expected )
506+
507+ def test_migrate_kv_format_already_new (self ):
508+ sensor = self .get_sensor_instance ()
509+ new_format = {
510+ 'rule1' : {'enforcement_id' : 'enforcement_id_1' , 'previous_state' : 'error' }
511+ }
512+
513+ result = sensor ._migrate_kv_format (new_format )
514+ self .assertEqual (result , new_format )
515+
516+ def test_get_previous_state (self ):
517+ sensor = self .get_sensor_instance ()
518+ sensor .kv_enforcements = {
519+ 'rule1' : {'enforcement_id' : 'id1' , 'previous_state' : 'error' },
520+ 'rule2' : {'enforcement_id' : 'id2' } # missing previous_state
521+ }
522+
523+ self .assertEqual (sensor ._get_previous_state ('rule1' ), 'error' )
524+ self .assertEqual (sensor ._get_previous_state ('rule2' ), 'unknown' )
525+ self .assertEqual (sensor ._get_previous_state ('nonexistent' ), 'unknown' )
526+
527+ def test_set_rule_state (self ):
528+ sensor = self .get_sensor_instance ()
529+ sensor .kv_enforcements = {}
530+
531+ sensor ._set_rule_state ('test_rule' , 'test_enforcement' , 'error' )
532+
533+ expected = {'test_rule' : {'enforcement_id' : 'test_enforcement' , 'previous_state' : 'error' }}
534+ self .assertEqual (sensor .kv_enforcements , expected )
535+
536+ def test_enhanced_trigger_dispatch_error (self ):
537+ sensor = self .get_sensor_instance ()
538+ sensor .st2_fqdn = 'st2_test'
539+ sensor .kv_enforcements = {}
540+
541+ test_dict = {
542+ 'st2_rule_name' : 'test_rule' ,
543+ 'st2_server' : 'st2_test' ,
544+ 'st2_execution_id' : 'st2_test_execution' ,
545+ 'st2_comments' : 'test_comments' ,
546+ 'st2_state' : 'error'
547+ }
548+
549+ sensor .dispatch_trigger (** test_dict )
550+
551+ # Check both triggers were dispatched
552+ trigger_payload = {
553+ 'st2_rule_name' : 'test_rule' ,
554+ 'st2_server' : 'st2_test' ,
555+ 'st2_execution_id' : 'st2_test_execution' ,
556+ 'st2_comments' : 'test_comments' ,
557+ 'st2_state' : 'error'
558+ }
559+
560+ enhanced_trigger_payload = trigger_payload .copy ()
561+ enhanced_trigger_payload ['st2_previous_state' ] = 'unknown'
562+
563+ self .assertTriggerDispatched (trigger = 'errors.error_cron_event' ,
564+ payload = trigger_payload )
565+ self .assertTriggerDispatched (trigger = 'errors.error_cron_event_enhanced' ,
566+ payload = enhanced_trigger_payload )
567+
568+ def test_enhanced_trigger_dispatch_success_with_previous_error (self ):
569+ sensor = self .get_sensor_instance ()
570+ sensor .st2_fqdn = 'st2_test'
571+ sensor .kv_enforcements = {'test_rule' : {'enforcement_id' : 'old_id' ,
572+ 'previous_state' : 'error' }}
573+
574+ test_dict = {
575+ 'st2_rule_name' : 'test_rule' ,
576+ 'st2_server' : 'st2_test' ,
577+ 'st2_execution_id' : 'new_execution' ,
578+ 'st2_comments' : 'Cronjob recovered' ,
579+ 'st2_state' : 'success' ,
580+ 'st2_enforcement_id' : 'new_enforcement'
581+ }
582+
583+ sensor .dispatch_trigger (** test_dict )
584+
585+ # Check both triggers were dispatched
586+ trigger_payload = {
587+ 'st2_rule_name' : 'test_rule' ,
588+ 'st2_server' : 'st2_test' ,
589+ 'st2_execution_id' : 'new_execution' ,
590+ 'st2_comments' : 'Cronjob recovered' ,
591+ 'st2_state' : 'success'
592+ }
593+
594+ enhanced_trigger_payload = trigger_payload .copy ()
595+ enhanced_trigger_payload ['st2_previous_state' ] = 'error'
596+
597+ self .assertTriggerDispatched (trigger = 'errors.error_cron_event' ,
598+ payload = trigger_payload )
599+ self .assertTriggerDispatched (trigger = 'errors.error_cron_event_enhanced' ,
600+ payload = enhanced_trigger_payload )
601+
602+ # Verify state was updated
603+ expected_kv = {'test_rule' : {'enforcement_id' : 'new_enforcement' ,
604+ 'previous_state' : 'success' }}
605+ self .assertEqual (sensor .kv_enforcements , expected_kv )
0 commit comments