diff --git a/moto/cloudwatch/models.py b/moto/cloudwatch/models.py index 19b1efa5f..f089acb14 100644 --- a/moto/cloudwatch/models.py +++ b/moto/cloudwatch/models.py @@ -304,6 +304,13 @@ class CloudWatchBackend(BaseBackend): ) def delete_alarms(self, alarm_names): + for alarm_name in alarm_names: + if alarm_name not in self.alarms: + raise RESTError( + "ResourceNotFound", + "Alarm {0} not found".format(alarm_name), + status=404, + ) for alarm_name in alarm_names: self.alarms.pop(alarm_name, None) diff --git a/tests/test_cloudwatch/test_cloudwatch_boto3.py b/tests/test_cloudwatch/test_cloudwatch_boto3.py index 0c814ee44..926c321ba 100644 --- a/tests/test_cloudwatch/test_cloudwatch_boto3.py +++ b/tests/test_cloudwatch/test_cloudwatch_boto3.py @@ -92,6 +92,37 @@ def test_get_dashboard_fail(): raise RuntimeError("Should of raised error") +@mock_cloudwatch +def test_delete_invalid_alarm(): + cloudwatch = boto3.client("cloudwatch", "eu-west-1") + + cloudwatch.put_metric_alarm( + AlarmName="testalarm1", + MetricName="cpu", + Namespace="blah", + Period=10, + EvaluationPeriods=5, + Statistic="Average", + Threshold=2, + ComparisonOperator="GreaterThanThreshold", + ActionsEnabled=True, + ) + + # trying to delete an alarm which is not created along with valid alarm. + with assert_raises(ClientError) as e: + cloudwatch.delete_alarms(AlarmNames=["InvalidAlarmName", "testalarm1"]) + e.exception.response["Error"]["Code"].should.equal("ResourceNotFound") + + resp = cloudwatch.describe_alarms(AlarmNames=["testalarm1"]) + # making sure other alarms are not deleted in case of an error. + len(resp["MetricAlarms"]).should.equal(1) + + # test to check if the error raises if only one invalid alarm is tried to delete. + with assert_raises(ClientError) as e: + cloudwatch.delete_alarms(AlarmNames=["InvalidAlarmName"]) + e.exception.response["Error"]["Code"].should.equal("ResourceNotFound") + + @mock_cloudwatch def test_alarm_state(): client = boto3.client("cloudwatch", region_name="eu-central-1")