# Buggy code
def parse_notification(notification):
    notification = json.loads(notification)

    if notification["Type"] == "SubscriptionConfirmation":
        return Alert(
            resource=notification["TopicArn"],
            event=notification["Type"],
            environment="Production",
            severity="informational",
            service=["Unknown"],
            group="AWS/CloudWatch",
            text='%s <a href="%s" target="_blank">SubscribeURL</a>'
            % (notification["Message"], notification["SubscribeURL"]),
            origin=notification["TopicArn"],
            event_type="cloudwatchAlarm",
            create_time=datetime.strptime(
                notification["Timestamp"], "%Y-%m-%dT%H:%M:%S.%fZ"
            ),
            raw_data=notification,
        )

    elif notification["Type"] == "Notification":
        alarm = json.loads(notification["Message"])

        if "Trigger" not in alarm:
            raise ValueError("SNS message is not a Cloudwatch notification")

        return Alert(
            resource="%s:%s"
            % (
                alarm["Trigger"]["Dimensions"][0]["name"],
                alarm["Trigger"]["Dimensions"][0]["value"],
            ),
            event=alarm["AlarmName"],
            environment="Production",
            severity=cw_state_to_severity(alarm["NewStateValue"]),
            service=[alarm["AWSAccountId"]],
            group=alarm["Trigger"]["Namespace"],
            value=alarm["NewStateValue"],
            text=alarm["AlarmDescription"],
            tags=[alarm["Region"]],
            attributes={
                "incidentKey": alarm["AlarmName"],
                "thresholdInfo": alarm["Trigger"],
            },
            origin=notification["TopicArn"],
            event_type="cloudwatchAlarm",
            create_time=datetime.strptime(
                notification["Timestamp"], "%Y-%m-%dT%H:%M:%S.%fZ"
            ),
            raw_data=alarm,
        )


# Traceback (TypeError)
Traceback (most recent call last):
File "/opt/alerta/venv/lib/python3.5/site-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/opt/alerta/venv/lib/python3.5/site-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/opt/alerta/venv/lib/python3.5/site-packages/flask_cors/decorator.py", line 128, in wrapped_function
resp = make_response(f(*args, **kwargs))
File "/opt/alerta/venv/lib/python3.5/site-packages/alerta/auth/utils.py", line 95, in wrapped
return f(*args, **kwargs)
File "/opt/alerta/venv/lib/python3.5/site-packages/alerta/webhooks/cloudwatch.py", line 81, in cloudwatch
incomingAlert = parse_notification(request.data)
File "/opt/alerta/venv/lib/python3.5/site-packages/alerta/webhooks/cloudwatch.py", line 29, in parse_notification
notification = json.loads(notification)
File "/usr/lib/python3.5/json/__init__.py", line 312, in loads
s.__class__.__name__))
TypeError: the JSON object must be str, not 'bytes'

# Fixed code
def parse_notification(notification):
    if notification["Type"] == "SubscriptionConfirmation":
        return Alert(
            resource=notification["TopicArn"],
            event=notification["Type"],
            environment="Production",
            severity="informational",
            service=["Unknown"],
            group="AWS/CloudWatch",
            text='%s <a href="%s" target="_blank">SubscribeURL</a>'
            % (notification["Message"], notification["SubscribeURL"]),
            origin=notification["TopicArn"],
            event_type="cloudwatchAlarm",
            create_time=datetime.strptime(
                notification["Timestamp"], "%Y-%m-%dT%H:%M:%S.%fZ"
            ),
            raw_data=notification,
        )

    elif notification["Type"] == "Notification":
        alarm = json.loads(notification["Message"])

        if "Trigger" not in alarm:
            raise ValueError("SNS message is not a Cloudwatch notification")

        return Alert(
            resource="%s:%s"
            % (
                alarm["Trigger"]["Dimensions"][0]["name"],
                alarm["Trigger"]["Dimensions"][0]["value"],
            ),
            event=alarm["AlarmName"],
            environment="Production",
            severity=cw_state_to_severity(alarm["NewStateValue"]),
            service=[alarm["AWSAccountId"]],
            group=alarm["Trigger"]["Namespace"],
            value=alarm["NewStateValue"],
            text=alarm["AlarmDescription"],
            tags=[alarm["Region"]],
            attributes={
                "incidentKey": alarm["AlarmName"],
                "thresholdInfo": alarm["Trigger"],
            },
            origin=notification["TopicArn"],
            event_type="cloudwatchAlarm",
            create_time=datetime.strptime(
                notification["Timestamp"], "%Y-%m-%dT%H:%M:%S.%fZ"
            ),
            raw_data=alarm,
        )