{
  "AWSTemplateFormatVersion" : "2010-09-09",

  "Description" : "AWS CloudFormation Sample Template RDS_MySQL_55: Sample template showing how to create a highly-available, RDS DBInstance version 5.5 with alarming on important metrics that indicate the health of the database **WARNING** This template creates an Amazon Relational Database Service database instance and Amazon CloudWatch alarms. You will be billed for the AWS resources used if you create a stack from this template.",

  "Parameters": {
    "DBName": {
      "Default": "MyDatabase",
      "Description" : "The database name",
      "Type": "String",
      "MinLength": "1",
      "MaxLength": "64",
      "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*",
      "ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters."
    },
    "DBUser": {
      "NoEcho": "true",
      "Description" : "The database admin account username",
      "Type": "String",
      "MinLength": "1",
      "MaxLength": "16",
      "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*",
      "ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters."
    },
    "DBPassword": {
      "NoEcho": "true",
      "Description" : "The database admin account password",
      "Type": "String",
      "MinLength": "8",
      "MaxLength": "41",
      "AllowedPattern" : "[a-zA-Z0-9]*",
      "ConstraintDescription" : "must contain only alphanumeric characters."
    },
    "DBAllocatedStorage": {
      "Default": "5",
      "Description" : "The size of the database (Gb)",
      "Type": "Number",
      "MinValue": "5",
      "MaxValue": "1024",
      "ConstraintDescription" : "must be between 5 and 1024Gb."
    },
    "DBInstanceClass": {
      "Default": "db.m1.small",
      "Description" : "The database instance type",
      "Type": "String",
      "AllowedValues" : [ "db.m1.small", "db.m1.large", "db.m1.xlarge", "db.m2.xlarge", "db.m2.2xlarge", "db.m2.4xlarge" ],
      "ConstraintDescription" : "must select a valid database instance type."
    },
    "EC2SecurityGroup": {
      "Default": "default",
      "Description" : "The EC2 security group that contains instances that need access to the database",
      "Type": "String"
    },
    "AlarmTopic": {
      "Description": "SNS topic to notify if there are operational issues",
      "Type": "String"
    },
    "MultiAZ": {
      "Default": "true",
      "Description" : "Create a multi-AZ RDS database instance",
      "Type": "String",
      "AllowedValues" : [ "true", "false" ],
      "ConstraintDescription" : "must be either true or false."
    }
  },

  "Mappings" : {
    "InstanceTypeMap" : {
      "db.m1.small" : {
        "CPULimit" : "60",
        "FreeStorageSpaceLimit" : "1024",
        "ReadIOPSLimit" : "100",
        "WriteIOPSLimit" : "100"
      },
      "db.m1.large" : {
        "CPULimit" : "60",
        "FreeStorageSpaceLimit" : "1024",
        "ReadIOPSLimit" : "100",
        "WriteIOPSLimit" : "100"
      },
      "db.m1.xlarge" : {
        "CPULimit" : "60",
        "FreeStorageSpaceLimit" : "1024",
        "ReadIOPSLimit" : "100",
        "WriteIOPSLimit" : "100"
      },
      "db.m2.xlarge" : {
        "CPULimit" : "60",
        "FreeStorageSpaceLimit" : "1024",
        "ReadIOPSLimit" : "100",
        "WriteIOPSLimit" : "100"
      },
      "db.m2.2xlarge" : {
        "CPULimit" : "60",
        "FreeStorageSpaceLimit" : "1024",
        "ReadIOPSLimit" : "100",
        "WriteIOPSLimit" : "100"
      },
      "db.m2.4xlarge" : {
        "CPULimit" : "60",
        "FreeStorageSpaceLimit" : "1024",
        "ReadIOPSLimit" : "100",
        "WriteIOPSLimit" : "100"
      }
    }
  },

  "Resources" : {

    "MyDB" : {
      "Type" : "AWS::RDS::DBInstance",
      "Properties" : {
        "DBName" : { "Ref" : "DBName" },
        "AllocatedStorage" : { "Ref" : "DBAllocatedStorage" },
        "DBInstanceClass" : { "Ref" : "DBInstanceClass" },
        "Engine" : "MySQL",
        "EngineVersion" : "5.5",
        "DBSecurityGroups": [ { "Ref": "DBSecurityGroup" } ],
        "MasterUsername" : { "Ref" : "DBUser" },
        "MasterUserPassword" : { "Ref" : "DBPassword" },
        "MultiAZ" : { "Ref" : "MultiAZ" }
      },
      "DeletionPolicy" : "Snapshot"
    },

    "DBSecurityGroup": {
      "Type": "AWS::RDS::DBSecurityGroup",
      "Properties": {
        "DBSecurityGroupIngress": {
          "EC2SecurityGroupName": { "Ref": "EC2SecurityGroup" }
        },
        "GroupDescription": "database access"
      }
    },

    "CPUAlarmHigh": {
      "Type": "AWS::CloudWatch::Alarm",
      "Properties": {
        "AlarmDescription": { "Fn::Join" : [ "", ["Alarm if ", { "Ref" : "DBName" }, " CPU > ", { "Fn::FindInMap" : [ "InstanceTypeMap", { "Ref" : "DBInstanceClass" }, "CPULimit" ]}, "% for 5 minutes" ]]},
        "Namespace": "AWS/RDS",
        "MetricName": "CPUUtilization",
        "Statistic": "Average",
        "Period": "60",
        "Threshold": { "Fn::FindInMap" : [ "InstanceTypeMap", { "Ref" : "DBInstanceClass" }, "CPULimit" ]},
        "ComparisonOperator": "GreaterThanThreshold",
        "EvaluationPeriods": "5",
        "AlarmActions": [ { "Ref": "AlarmTopic" } ],
        "Dimensions": [{
            "Name": "DBInstanceIdentifier",
            "Value": { "Ref": "MyDB" }
        }]
      }
    },
    "FreeStorageSpace": {
      "Type": "AWS::CloudWatch::Alarm",
      "Properties": {
        "AlarmDescription": { "Fn::Join" : [ "", ["Alarm if ", { "Ref" : "DBName" }, " storage space <= ", { "Fn::FindInMap" : [ "InstanceTypeMap", { "Ref" : "DBInstanceClass" }, "FreeStorageSpaceLimit" ]}, " for 5 minutes" ]]},
        "Namespace": "AWS/RDS",
        "MetricName": "FreeStorageSpace",
        "Statistic": "Average",
        "Period": "60",
        "Threshold": { "Fn::FindInMap" : [ "InstanceTypeMap", { "Ref" : "DBInstanceClass" }, "FreeStorageSpaceLimit" ]},
        "ComparisonOperator": "LessThanOrEqualToThreshold",
        "EvaluationPeriods": "5",
        "AlarmActions": [ { "Ref": "AlarmTopic" } ],
        "Dimensions": [{
            "Name": "DBInstanceIdentifier",
            "Value": { "Ref": "MyDB" }
        }]
      }
    },
    "ReadIOPSHigh": {
      "Type": "AWS::CloudWatch::Alarm",
      "Properties": {
        "AlarmDescription": { "Fn::Join" : [ "", ["Alarm if ", { "Ref" : "DBName" }, " WriteIOPs > ", { "Fn::FindInMap" : [ "InstanceTypeMap", { "Ref" : "DBInstanceClass" }, "ReadIOPSLimit" ]}, " for 5 minutes" ]]},
        "Namespace": "AWS/RDS",
        "MetricName": "ReadIOPS",
        "Statistic": "Average",
        "Period": "60",
        "Threshold": { "Fn::FindInMap" : [ "InstanceTypeMap", { "Ref" : "DBInstanceClass" }, "ReadIOPSLimit" ]},
        "ComparisonOperator": "GreaterThanThreshold",
        "EvaluationPeriods": "5",
        "AlarmActions": [ { "Ref": "AlarmTopic" } ],
        "Dimensions": [{
            "Name": "DBInstanceIdentifier",
            "Value": { "Ref": "MyDB" }
        }]
      }
    },
    "WriteIOPSHigh": {
      "Type": "AWS::CloudWatch::Alarm",
      "Properties": {
        "AlarmDescription": { "Fn::Join" : [ "", ["Alarm if ", { "Ref" : "DBName" }, " WriteIOPs > ", { "Fn::FindInMap" : [ "InstanceTypeMap", { "Ref" : "DBInstanceClass" }, "WriteIOPSLimit" ]}, " for 5 minutes" ]]},
        "Namespace": "AWS/RDS",
        "MetricName": "WriteIOPS",
        "Statistic": "Average",
        "Period": "60",
        "Threshold": { "Fn::FindInMap" : [ "InstanceTypeMap", { "Ref" : "DBInstanceClass" }, "WriteIOPSLimit" ]},
        "ComparisonOperator": "GreaterThanThreshold",
        "EvaluationPeriods": "5",
        "AlarmActions": [ { "Ref": "AlarmTopic" } ],
        "Dimensions": [{
            "Name": "DBInstanceIdentifier",
            "Value": { "Ref": "MyDB" }
        }]
      }
    }
  },

  "Outputs" : {
    "JDBCConnectionString": {
      "Description" : "JDBC connection string for database",
      "Value" : { "Fn::Join": [ "", [ "jdbc:mysql://",
                                      { "Fn::GetAtt": [ "MyDB", "Endpoint.Address" ] },
                                      ":",
                                      { "Fn::GetAtt": [ "MyDB", "Endpoint.Port" ] },
                                      "/",
                                      { "Ref": "DBName" }]]}
    },
    "DBAddress" : {
      "Description" : "Address of database endpoint",
      "Value" : { "Fn::GetAtt": [ "MyDB", "Endpoint.Address" ] }
    },
    "DBPort" : {
      "Description" : "Database endpoint port number",
      "Value" : { "Fn::GetAtt": [ "MyDB", "Endpoint.Port" ] }
    }
  }
}
