---
AWSTemplateFormatVersion: '2010-09-09'
Description: MySQL RDS by Levon Becker v20160410-0900
Parameters:
  Owner:
    Description: Enter Team or Individual Name Responsible for the Stack.
    Type: String
    Default: FirstName LastName
  Project:
    Description: Enter Project Name.
    Type: String
    Default: MySQL RDS Creation
  DeleteAfter:
    Description: Enter Date It's Ok to Delete the Stack or 'Never' if meant to be
      persistent.
    Type: String
    Default: 00/00/201x
  VPC:
    Description: Select VPC.
    Type: AWS::EC2::VPC::Id
  PrivateSubnet1:
    Description: Private Subnet 1 to Allow Routing.
    Type: AWS::EC2::Subnet::Id
  PrivateSubnet2:
    Description: Private Subnet 2 to Allow Routing.
    Type: AWS::EC2::Subnet::Id
  PrivateSubnet3:
    Description: Private Subnet 3 to Allow Routing.
    Type: AWS::EC2::Subnet::Id
  MasterUsername:
    Description: Database administration name. First character must be a letter and
      can not be 'root'.
    Type: String
    Default: rdsroot
  MasterUserPassword:
    NoEcho: 'true'
    Description: Database administration password. Minimum of 8 alphanumeric characters (pattern of [a-zA-Z0-9]).
    Type: String
    MinLength: '8'
    AllowedPattern: "[a-zA-Z0-9!?]*"
    ConstraintDescription: Must only contain upper and lowercase letters and numbers
  BackupRetentionPeriod:
    Description: Enter Backup Retention Period in Days.
    Type: Number
    Default: '7'
  MultiAvailabilityZone:
    Description: Enable Multi Availability Zones?
    Type: String
    Default: 'false'
    AllowedValues:
    - 'true'
    - 'false'
  TcpPort:
    Description: Enter RDS Listening TCP Port number.
    Type: Number
    Default: '3306'
  ConfigureDns:
    Description: Configure Route 53 DNS Alias for RDS? Be sure a matching record doesn't already exist.
    Type: String
    Default: 'false'
    AllowedValues:
    - 'true'
    - 'false'
  Cname:
    Description: "(Skip if Not Configuring Route 53) DNS Record to Update for the
      RDS Instance."
    Type: String
    Default: db.domain.com
  R53HostedZoneName:
    Description: "(Skip if Not Configuring Route 53) Hosted DNS Name."
    Type: String
    Default: domain.com
  AlertSnsTopicArn:
    Description: Enter Alert Notification SNS Topic ARN for RDS.
    Type: String
    Default: arn:aws:sns:us-west-2:000000000000:rds-alerts
  PreferredBackupWindow:
    Description: Enter Preferred Backup Window Time (UTC).
    Type: String
    Default: 17:00-19:00
  PreferredMaintenanceWindow:
    Description: Enter Preferred Maintenance Window Time (UTC).
    Type: String
    Default: Sun:19:00-Sun:23:00
  AllocatedStorage:
    Default: '5'
    Description: The size of the database (Gb)
    Type: Number
    MinValue: '5'
    MaxValue: '6144'
    ConstraintDescription: Must be between 5-6144
  ConfigureProvisionedIops:
    Description: Configure Route 53 DNS Alias for RDS? Be sure a matching record doesn't already exist.
    Type: String
    Default: 'false'
    AllowedValues:
    - 'true'
    - 'false'
  SnapshotOnDelete:
    Description: Create a Snapshot on Delete?
    Type: String
    Default: 'true'
    AllowedValues:
    - 'true'
    - 'false'
  AutoMinorVersionUpgrade:
    Description: Allow Automatic Minor Version Upgrades?
    Type: String
    Default: 'true'
    AllowedValues:
    - 'true'
    - 'false'
  SetupAlarms:
    Description: Setup Cloudwatch Alarms?
    Type: String
    Default: 'true'
    AllowedValues:
    - 'true'
    - 'false'
  ProvisionedIopsValue:
    Description: "(Skip if Not Using Provisioned IOPS) Set Provisioned IOPS 1000-30000."
    Type: Number
    Default: '1000'
    MinValue: '1000'
    MaxValue: '30000'
  InstanceType:
    Description: Select Instance Type.
    Type: String
    Default: db.t2.small
    AllowedValues:
    - db.t1.micro
    - db.t2.micro
    - db.t2.small
    - db.t2.medium
    - db.t2.large
    - db.m1.small
    - db.m1.medium
    - db.m1.large
    - db.m1.xlarge
    - db.m3.medium
    - db.m3.large
    - db.m3.xlarge
    - db.m3.2xlarge
    - db.m4.large
    - db.m4.xlarge
    - db.m4.2xlarge
    - db.m4.4xlarge
    - db.m4.10xlarge
    - db.r3.large
    - db.r3.xlarge
    - db.r3.2xlarge
    - db.r3.4xlarge
    - db.r3.8xlarge
    ConstraintDescription: Must be a valid EC2 instance type.
Mappings:
  Settings:
    MySQL:
      Engine: MySQL
      Version: '5.7'
Conditions:
  ConfigureRoute53:
    Fn::Equals:
    - Ref: ConfigureDns
    - 'true'
  ConfigureAlarms:
    Fn::Equals:
    - Ref: SetupAlarms
    - 'true'
  ConfigureSnapshotOnDelete:
    Fn::Equals:
    - Ref: SnapshotOnDelete
    - 'true'
Resources:
  RDSAccessSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Instance to RDS Access
      VpcId:
        Ref: VPC
      Tags:
      - Key: Name
        Value:
          Fn::Join:
          - ''
          - - Ref: AWS::StackName
            - "-rds"
      - Key: Owner
        Value:
          Ref: Owner
      - Key: Project
        Value:
          Ref: Project
      - Key: DeleteAfter
        Value:
          Ref: DeleteAfter
  AccessSecurityGroupIngress:
    Type: AWS::EC2::SecurityGroupIngress
    DependsOn: RDSAccessSecurityGroup
    Properties:
      GroupId:
        Ref: RDSAccessSecurityGroup
      IpProtocol: tcp
      FromPort:
        Ref: TcpPort
      ToPort:
        Ref: TcpPort
      SourceSecurityGroupId:
        Ref: RDSAccessSecurityGroup
  DbSubnetGroup:
    Type: AWS::RDS::DBSubnetGroup
    Properties:
      DBSubnetGroupDescription:
        Fn::Join:
        - ''
        - - 'RDS Subnet Group for '
          - Ref: AWS::StackName
      SubnetIds:
      - Ref: PrivateSubnet1
      - Ref: PrivateSubnet2
      - Ref: PrivateSubnet3
      Tags:
      - Key: Name
        Value:
          Ref: AWS::StackName
      - Key: Owner
        Value:
          Ref: Owner
      - Key: Project
        Value:
          Ref: Project
      - Key: DeleteAfter
        Value:
          Ref: DeleteAfter
  DbInstance:
    Type: AWS::RDS::DBInstance
    DeletionPolicy: Snapshot
    DependsOn:
    - DbSubnetGroup
    - RDSAccessSecurityGroup
    Properties:
      AllocatedStorage:
        Ref: AllocatedStorage
      AllowMajorVersionUpgrade: 'false'
      AutoMinorVersionUpgrade:
        Ref: AutoMinorVersionUpgrade
      BackupRetentionPeriod:
        Ref: BackupRetentionPeriod
      DBInstanceClass:
        Ref: InstanceType
      DBInstanceIdentifier:
        Ref: AWS::StackName
      DBSubnetGroupName:
        Ref: DbSubnetGroup
      Engine:
        Fn::FindInMap:
        - Settings
        - MySQL
        - Engine
      EngineVersion:
        Fn::FindInMap:
        - Settings
        - MySQL
        - Version
      MasterUsername:
        Ref: MasterUsername
      MasterUserPassword:
        Ref: MasterUserPassword
      MultiAZ:
        Ref: MultiAvailabilityZone
      Port:
        Ref: TcpPort
      PreferredBackupWindow:
        Ref: PreferredBackupWindow
      PreferredMaintenanceWindow:
        Ref: PreferredMaintenanceWindow
      PubliclyAccessible: 'false'
      StorageEncrypted: 'false'
      StorageType: gp2
      VPCSecurityGroups:
      - Ref: RDSAccessSecurityGroup
      Tags:
      - Key: Name
        Value:
          Ref: AWS::StackName
      - Key: Owner
        Value:
          Ref: Owner
      - Key: Project
        Value:
          Ref: Project
      - Key: DeleteAfter
        Value:
          Ref: DeleteAfter
  AlarmCpu:
    Condition: ConfigureAlarms
    Type: AWS::CloudWatch::Alarm
    DependsOn:
    - DbInstance
    Properties:
      AlarmActions:
      - Ref: AlertSnsTopicArn
      AlarmDescription: CPU Utilization on RDS Instance is too high
      ComparisonOperator: GreaterThanOrEqualToThreshold
      Dimensions:
      - Name: DBInstanceIdentifier
        Value:
          Ref: DbInstance
      EvaluationPeriods: '1'
      MetricName: CPUUtilization
      Namespace: AWS/RDS
      Period: '300'
      Statistic: Average
      Threshold: '50'
  AlarmFreeSpace:
    Condition: ConfigureAlarms
    Type: AWS::CloudWatch::Alarm
    DependsOn:
    - DbInstance
    Properties:
      AlarmActions:
      - Ref: AlertSnsTopicArn
      AlarmDescription: 1Gb left of storage available on RDS Instance
      ComparisonOperator: LessThanOrEqualToThreshold
      Dimensions:
      - Name: DBInstanceIdentifier
        Value:
          Ref: DbInstance
      EvaluationPeriods: '1'
      MetricName: FreeStorageSpace
      Namespace: AWS/RDS
      Period: '300'
      Statistic: Maximum
      Threshold: '1024000000'
  RecordSet:
    Condition: ConfigureRoute53
    Type: AWS::Route53::RecordSet
    DependsOn: DbInstance
    Properties:
      HostedZoneName:
        Fn::Join:
        - ''
        - - Ref: R53HostedZoneName
          - "."
      Comment: CNAME Redirect to the RDS
      Name:
        Fn::Join:
        - ''
        - - Ref: Cname
          - "."
      Type: CNAME
      TTL: '300'
      ResourceRecords:
      - Fn::GetAtt:
        - DbInstance
        - Endpoint.Address
Outputs:
  Owner:
    Description: Team or Individual that Owns this Formation.
    Value:
      Ref: Owner
  Project:
    Description: The project name
    Value:
      Ref: Project
  VPC:
    Description: VPC Used
    Value:
      Ref: VPC
  RDSHostname:
    Description: RDS Hostname
    Value:
      Fn::GetAtt:
      - DbInstance
      - Endpoint.Address
  RDSPort:
    Description: RDS Port
    Value:
      Fn::GetAtt:
      - DbInstance
      - Endpoint.Port
  DbSubnetGroup:
    Description: DB Subnet Group Created.
    Value:
      Ref: DbSubnetGroup
  RDSAccessSecurityGroup:
    Description: RDS Access Security Group Created.
    Value:
      Ref: RDSAccessSecurityGroup
  ConfigureDns:
    Description: Configure Route 53 DNS Option.
    Value:
      Ref: ConfigureDns
  R53HostedZoneName:
    Condition: ConfigureRoute53
    Description: Route 53 Zone Updated.
    Value:
      Ref: R53HostedZoneName
  Cname:
    Condition: ConfigureRoute53
    Description: Route 53 DNS Alias Created for RDS.
    Value:
      Ref: Cname
  AlarmCpu:
    Condition: ConfigureAlarms
    Description: CPU Alarm Created for RDS Instance/s.
    Value:
      Ref: AlarmCpu
  AlarmFreeSpace:
    Condition: ConfigureAlarms
    Description: Disk Free Space Alarm Created for RDS Instance/s.
    Value:
      Ref: AlarmFreeSpace
  PrivateSubnet1:
    Description: Private Subnet 1 Deployment
    Value:
      Ref: PrivateSubnet1
  PrivateSubnet2:
    Description: Private Subnet 2 Deployment
    Value:
      Ref: PrivateSubnet2
  PrivateSubnet3:
    Description: Private Subnet 3 Deployment
    Value:
      Ref: PrivateSubnet3
  BackupRetentionPeriod:
    Description: Backup Retention Period in Days
    Value:
      Ref: BackupRetentionPeriod
  MultiAvailabilityZone:
    Description: Enable Multi Availability Zones?
    Value:
      Ref: MultiAvailabilityZone
  SnapshotOnDelete:
    Description: Create Snapshot on Delete?
    Value:
      Ref: SnapshotOnDelete
  AlertSnsTopicArn:
    Description: SNS Topic ARN for Alerts
    Value:
      Ref: AlertSnsTopicArn
  PreferredBackupWindow:
    Description: Preferred Backup Window
    Value:
      Ref: PreferredBackupWindow
  PreferredMaintenanceWindow:
    Description: Preferred Maintenance Window
    Value:
      Ref: PreferredMaintenanceWindow
  AllocatedStorage:
    Description: Allocated Storage in GB
    Value:
      Ref: AllocatedStorage
  ConfigureProvisionedIops:
    Description: Configure Provisioned IOPS?
    Value:
      Ref: ConfigureProvisionedIops
  DeleteAfter:
    Description: It is ok to delete the Formation after this date
    Value:
      Ref: DeleteAfter
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
    - Label:
        default: Ownership
      Parameters:
      - Owner
      - Project
      - DeleteAfter
    - Label:
        default: Network Configuration
      Parameters:
      - VPC
      - PrivateSubnet1
      - PrivateSubnet2
      - PrivateSubnet3
    - Label:
        default: RDS Configuration
      Parameters:
      - InstanceType
      - MasterUsername
      - MasterUserPassword
      - BackupRetentionPeriod
      - PreferredBackupWindow
      - PreferredMaintenanceWindow
      - SnapshotOnDelete
      - AllocatedStorage
      - ConfigureProvisionedIops
      - ProvisionedIopsValue
      - AutoMinorVersionUpgrade
      - TcpPort
      - MultiAvailabilityZone
    - Label:
        default: Route 53 DNS Configuration
      Parameters:
      - ConfigureDns
      - R53HostedZoneName
      - Cname
    - Label:
        default: CloudWatch Monitoring
      Parameters:
      - SetupAlarms
      - AlertSnsTopicArn
    ParameterLabels:
      Owner:
        default: Team or Individual Owner
      DeleteAfter:
        default: Delete After Date
      InstanceType:
        default: Instance Type
      PrivateSubnet1:
        default: Private Subnet 1
      PrivateSubnet2:
        default: Private Subnet 2
      PrivateSubnet3:
        default: Private Subnet 3
      R53HostedZoneName:
        default: Hosted Zone
      Cname:
        default: RDS DNS Alias
      AlertSnsTopicArn:
        default: Alert SNS Topic ARN
      MasterUsername:
        default: Master Username
      MasterUserPassword:
        default: Master User Password
      BackupRetentionPeriod:
        default: Backup Retention Period
      PreferredBackupWindow:
        default: Preferred Backup Window
      PreferredMaintenanceWindow:
        default: Preferred Maintenance Window
      AllocatedStorage:
        default: Allocated Storage
      ConfigureProvisionedIops:
        default: Configure Provisioned IOPS?
      ProvisionedIopsValue:
        default: Provisioned IOPS Value
      AutoMinorVersionUpgrade:
        default: Auto Minor Version Upgrade
      TcpPort:
        default: TCP Port
      MultiAvailabilityZone:
        default: Multi Availability Zone?
      SetupAlarms:
        default: Setup Alarms?
      SnapshotOnDelete:
        default: Snapshot On Delete?
      ConfigureDns:
        default: Configure DNS
