AWSTemplateFormatVersion: 2010-09-09
Description: This stack will be used to deploy the AWS DMS automation framework for existing VPC (qs-1qcbthe9p)

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
    - Label: 
        default: Network configuration
      Parameters:
      - VPCID
      - PrivateSubnet1ID
      - PrivateSubnet2ID
      - PublicSubnet1ID
      - PublicSubnet2ID
      - ExistingSgID
      - EnableBastion
      - KeyPairName
      - RemoteAccessCIDR
    - Label:
        default: Migration setup
      Parameters:
      - CreateNewReplicationInstance
      - MigNotify
      - FullLoadOnly
      - TaskName
      - S3BucketName
      - S3BucketKey
    - Label:
        default: AWS DMS configuration for new replication instance (optional)
      Parameters:
        - DmsEngineVersion
        - DmsInstanceType
        - DmsMultiAz
    - Label: 
        default: AWS DMS configuration for new source endpoints (optional)
      Parameters:
      - SourceDBName
      - SourceEngine
      - SourcePassword
      - SourcePort
      - SourceEndpointServer
      - SourceUser
    - Label: 
        default: Target Endpoint Configuration
      Parameters:
      - TargetDBName
      - TargetEngine
      - TargetPassword
      - TargetPort
      - TargetEndpointServer
      - TargetUser
    - Label: 
        default: AWS DMS configuration for existing endpoints and replication instance
      Parameters:
      - DmsSourceArn
      - DmsTargetArn
      - DmsReplicationArn
    - Label: 
        default: AWS Quick Start configuration 
      Parameters:
      - QSS3BucketName
      - QSS3KeyPrefix
      
    # Parameter Labels
    ParameterLabels:
      S3BucketName:
        default: Migration bucket name
      S3BucketKey:
        default: Migration bucket key
      DmsEngineVersion:
       default: AWS DMS Engine version
      DmsInstanceType:
        default: Instance type
      DmsMultiAz:
        default: Multi AZ
      FullLoadOnly:
        default: Full load only
      CreateSample:
        default: Create sample
      MigNotify:
        default: Notification email
      TaskName:
        default: Task Name
      DmsSourceArn:
        default: AWS DMS source endpoint ARN
      DmsTargetArn:
        default: AWS DMS target endpoint ARN
      DmsReplicationArn:
        default: AWS DMS replication instance endpoint ARN
      CreateNewReplicationInstance:
        default: Create new replication instance?
      SourceDBName:
        default: Source DB name
      SourceEngine:
        default: Source DB engine
      SourcePassword:
        default: Source DB password
      SourcePort:
        default: Source DB port
      SourceEndpointServer:
        default: Source DB server
      SourceUser:
        default: Source user
      TargetDBName:
        default: Target DB name
      TargetEngine:
        default: Target DB engine
      TargetPassword:
        default: Target DB password
      TargetPort:
        default: Target DB port
      TargetEndpointServer:
        default: Target DB server
      TargetUser:
        default: Target DB user
      VPCID:
        default: VPC ID
      PrivateSubnet1ID:
        default: Private subnet 1 ID
      PrivateSubnet2ID:
        default: Private subnet 2 ID
      PublicSubnet1ID:
        default: Public subnet 1 ID
      PublicSubnet2ID:
        default: Public subnet 2 ID
      ExistingSgID:
        default: Security group ID
      AvailabilityZones:
        default: Availability Zones
      KeyPairName:
        default: Key pair name
      RemoteAccessCIDR:
        default: Remote Access CIDR
      EnableBastion:
        default: Enable bastion
      QSS3BucketName:
        default: Quickstart S3 Bucket Name
      QSS3KeyPrefix:
        default: Quickstart S3 Prefix
Parameters:
  S3BucketName:
    Type: String
    Default: ''
    Description: The name of the S3 bucket that contains all the zip files necessary for the migration. If left blank, a versioned bucket is created for you.
  S3BucketKey:
    Type: String
    Description: S3 bucket key which has all the zip files necessary for migration. Although the bucket may not exist, this value will trigger the entire automation. Can be uploaded after the pipeline is created.
    AllowedPattern: ^(?!\s*$).+
    ConstraintDescription: 'Cannot be null or whitespace'
  FullLoadOnly:
    Type: String
    Description: Full-load migration. Choose yes if the migration does not include CDC.
    AllowedValues:
      - 'yes'
      - 'no'
    Default: 'no'
  MigNotify:
    Type: String
    Description: The email address that receives notifications on the migration status.
    AllowedPattern: '^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'
    ConstraintDescription: provide a valid email address.
  TaskName:
    Type: String
    Description: The name of the AWS DMS task. If left empty, the stack name is used.
    Default: ''
  DmsSourceArn:
    Type: String
    Description: The Amazon Resource Name (ARN) of the source endpoint which was successfully tested with replication instance. 
      instance
    Default: ''
  DmsTargetArn:
    Type: String
    Description: The Amazon Resource Name (ARN) of the source endpoint which was successfully tested with replication instance. 
    Default: ''
  DmsReplicationArn:
    Type: String
    Description: The ARN of the replication instance that is used for the migration. You must include this if CreateNewReplicationInstance is set to no.
    Default: ''
  CreateNewReplicationInstance:
    Type: String
    Default: 'no'
    AllowedValues:
      - 'yes'
      - 'no'
    Description: New replication instance. Choose no if you are planning to use an existing replication instance.
  SourceDBName:
    Type: String
    Description: The name of the database or service name on the source server. Leave this blank if you have an existing AWS DMS Source endpoint ARN.
    Default: ''
  SourceEngine:
    Type: String
    Description: The database engine running on the source database. If existing DMS Source endpoint ARN is provided, this is ignored.
    Default: oracle
    AllowedValues:
      - mysql
      - oracle
      - postgres
      - mariadb
      - db2
      - azuredb
      - sybase
      - sqlserver
  SourcePassword:
    Type: String
    Description: The password for the source database. Leave this blank if you have an existing AWS DMS Source endpoint ARN.
    NoEcho: 'true'
    Default: ''
  SourcePort:
    Type: String
    Description: The port on which the source database is running. If existing DMS Source endpoint ARN is provided, this is ignored.
    Default: '1521'
  SourceEndpointServer:
    Type: String
    Description: The source database hostname, endpoint URL, or IP address. Leave this blank if you have an existing AWS DMS Source endpoint ARN.
    Default: ''
  SourceUser:
    Type: String
    Description: The user name for accessing the source database.. Leave this blank if you have an existing AWS DMS Source endpoint ARN.
    Default: ''
  TargetDBName:
    Type: String
    Description: The name of the database or service name on the target server. 
    AllowedPattern: ^(?!\s*$).+
  TargetEngine:
    Type: String
    Description: The database engine running on the target database. If existing DMS Target endpoint ARN is provided, this is ignored.
    Default: aurora-postgresql
    AllowedValues:
      - mysql
      - oracle
      - postgres
      - mariadb
      - aurora
      - aurora-postgresql
      - redshift
      - sqlserver
  TargetPassword:
    Type: String
    Description: The password for the target database. 
    NoEcho: 'true'
    AllowedPattern: ^(?!\s*$).+
    ConstraintDescription: 'Cannot be null or whitespace'
  TargetPort:
    Type: Number
    Description: The port on which the target database is running. If existing DMS Target endpoint ARN is provided, this is ignored.
    Default: '5432'
    ConstraintDescription: 'Must be in the range [1115-65535].'
    MinValue: 1150
    MaxValue: 65535
  TargetEndpointServer:
    Type: String
    Description: The target database hostname, endpoint URL, or IP address. 
    AllowedPattern: ^(?!\s*$).+
    ConstraintDescription: 'Cannot be null or whitespace'
  TargetUser:
    Type: String
    Description: The user name for accessing the target database. 
    AllowedPattern: ^(?!\s*$).+
    ConstraintDescription: 'Cannot be null or whitespace'
  VPCID:
    Description: The ID of your existing VPC (e.g., vpc-0343606e).
    Type: 'AWS::EC2::VPC::Id'
  PrivateSubnet1ID:
    Description: The ID of the private subnet in Availability Zone 1 in your existing VPC (e.g., subnet-a0246dcd).
    Type: 'AWS::EC2::Subnet::Id'
  PrivateSubnet2ID:
    Description: The ID of the private subnet in Availability Zone 2 in your existing VPC (e.g., subnet-a0246dcd).
    Type: 'AWS::EC2::Subnet::Id'
  PublicSubnet1ID:
    Description: The ID of the public subnet in Availability Zone 1 in your existing VPC (e.g., subnet-a0246dcd).
    Type: 'AWS::EC2::Subnet::Id'
  PublicSubnet2ID:
    Description: The ID of the public subnet in Availability Zone 2 in your existing VPC (e.g., subnet-a0246dcd).
    Type: 'AWS::EC2::Subnet::Id'
  ExistingSgID:
    Description: The security group ID in your existing VPC (e.g., sg-7f16e910) which has access to source and target databases. It should also be self-referenced.
    Type: 'AWS::EC2::SecurityGroup::Id'
  KeyPairName: 
    ConstraintDescription: "The name of an existing public/private key pair, for connecting to your instance."
    Description: The name of an existing public/private key pair, for connecting to your instance.
    Type: "AWS::EC2::KeyPair::KeyName"
  RemoteAccessCIDR:
    AllowedPattern: "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/([0-9]|[1-2][0-9]|3[0-2]))$"
    ConstraintDescription: "CIDR block parameter must be in the form x.x.x.x/x"
    Description: "Allowed CIDR block for external SSH access."
    Default: 10.0.0.0/16
    Type: String
  EnableBastion:
    AllowedValues:
      - "true"
      - "false"
    Default: "false"
    Description: "Bastion host deployment. Choose true to create a bastion stack."
    Type: String
  QSS3BucketName:
    AllowedPattern: "^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$"
    ConstraintDescription: "Quick Start bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-)."
    Default: aws-quickstart
    Description: "S3 bucket name for the Quick Start assets. Quick Start bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-)."
    Type: String
  QSS3KeyPrefix:
    AllowedPattern: "^[0-9a-zA-Z-/]*$"
    ConstraintDescription: "Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), and forward slash (/)."
    Default: quickstart-aws-dms-automation/
    Description: "S3 key prefix for the Quick Start assets. Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), and forward slash (/)."
    Type: String
  DmsEngineVersion: 
    Default: 3.1.4
    Type: String
    Description: AWS DMS replication engine version. If existing replication instance ARN is provided, this is ignored.
    AllowedValues:
      - 3.1.4
      - 2.4.5
      - 2.4.4
      - 2.4.3
  DmsInstanceType:
    Default: dms.c4.large
    Type: String
    Description: AWS DMS replication instance size. If existing replication instance ARN is provided, this is ignored.
    AllowedValues:
      - dms.t2.micro
      - dms.t2.small
      - dms.t2.medium
      - dms.t2.large
      - dms.c4.large
      - dms.c4.xlarge
      - dms.c4.2xlarge
      - dms.c4.4xlarge
  DmsMultiAz: 
    Default: 'true'
    Type: String
    Description: AWS DMS replication instance deployment across multiple Availability Zones. If existing replication instance ARN is provided, this is ignored.
    AllowedValues:
      - 'true'
      - 'false'
      
    
Conditions:
  CreateBastion: 
    !Equals [!Ref EnableBastion, 'true']
  CreateReplicationInst:
    !Equals [!Ref CreateNewReplicationInstance, 'yes']
  CreateBucket:
    !Equals [!Ref S3BucketName, '']
Resources:

  BastionStack:
    Condition: CreateBastion
    Type: 'AWS::CloudFormation::Stack'
    Properties:
      TemplateURL: !Sub https://${QSS3BucketName}.s3.amazonaws.com/${QSS3KeyPrefix}submodules/quickstart-linux-bastion/templates/linux-bastion.template

      Parameters:
        KeyPairName: !Ref KeyPairName
        PublicSubnet1ID: !Ref PublicSubnet1ID
        PublicSubnet2ID: !Ref PublicSubnet2ID
        RemoteAccessCIDR: !Ref RemoteAccessCIDR
        VPCID: !Ref VPCID
  
  S3Bucket:
    Condition: CreateBucket
    Type: AWS::S3::Bucket
    Properties:
      VersioningConfiguration:
        Status: Enabled


  DMSCodePiplineStack:
    Type: 'AWS::CloudFormation::Stack'
    Properties:
      TemplateURL: !Sub https://${QSS3BucketName}.s3.amazonaws.com/${QSS3KeyPrefix}templates/dms-automation-code-pipeline.template.yaml
      Parameters:
        MigNotify: !Ref MigNotify
        TaskName: !Ref TaskName
        CodeBuildVpc: !Ref VPCID
        CodeBuildSubnet: !Ref PrivateSubnet1ID
        CodeBuildSecurityGroup: !Ref ExistingSgID
        S3BucketName: !If [CreateBucket, !Ref S3Bucket, !Ref S3BucketName]
        S3BucketKey: !Ref S3BucketKey
        TargetEndpoint: !Ref TargetEndpointServer
        TargetDbName: !Ref TargetDBName
        TargetDbUser: !Ref TargetUser
        TargetDbPassword: !Ref TargetPassword
        DmsSourceArn: !If [CreateReplicationInst, !GetAtt DMSReplicationStack.Outputs.SourceEndpointArn ,!Ref DmsSourceArn]
        DmsTargetArn: !If [CreateReplicationInst, !GetAtt DMSReplicationStack.Outputs.TargetEndpointArn ,!Ref DmsTargetArn]
        DmsReplicationArn: !If [CreateReplicationInst, !GetAtt DMSReplicationStack.Outputs.ReplicationInstanceArn ,!Ref DmsReplicationArn]
        CreateSample: 'no'
        FullLoadOnly: !Ref FullLoadOnly
        SourceEndpoint: !Ref SourceEndpointServer
        SourceDbName: !Ref SourceDBName
        SourceDbPassword: !Ref SourcePassword
        SourceDbUser: !Ref SourceUser 
        


  DMSReplicationStack:
    Condition: CreateReplicationInst
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: !Sub https://${QSS3BucketName}.s3.amazonaws.com/${QSS3KeyPrefix}templates/dms-automation-replication-setup.template.yaml
      Parameters:
        CreateNewReplicationInstance: !Ref CreateNewReplicationInstance
        ReplInstanceArn: !Ref DmsReplicationArn
        PrivateSubnet1: !Ref PrivateSubnet1ID
        PrivateSubnet2: !Ref PrivateSubnet2ID
        SecurityGroup: !Ref ExistingSgID
        MultiAz: !Ref DmsMultiAz
        InstanceType: !Ref DmsInstanceType
        EngineVersion: !Ref DmsEngineVersion
        SourceDBName: !Ref SourceDBName
        SourceEngine: !Ref SourceEngine
        SourcePassword: !Ref SourcePassword
        SourcePort: !Ref SourcePort
        SourceEndpointServer: !Ref SourceEndpointServer
        SourceUser: !Ref SourceUser
        TargetDBName: !Ref TargetDBName
        TargetEngine: !Ref TargetEngine
        TargetPassword: !Ref TargetPassword
        TargetPort: !Ref TargetPort
        TargetEndpointServer: !Ref TargetEndpointServer
        TargetUser: !Ref TargetUser

Outputs:
  MigrationBucket:
    Description: S3 Bucket for triggering the automation
    Value: !If [CreateBucket, !Ref S3Bucket, !Ref S3BucketName]
  MigrationPipeline:
    Description: CodePipeline for DMS migration
    Value: !GetAtt DMSCodePiplineStack.Outputs.DmsPipeline