|
1 | | -locals {} |
| 1 | +provider "aws" { |
| 2 | + region = local.region |
| 3 | +} |
| 4 | + |
| 5 | +locals { |
| 6 | + region = "us-east-1" |
| 7 | + name = "dms-example-${replace(basename(path.cwd), "_", "-")}" |
| 8 | + |
| 9 | + db_name = "example" |
| 10 | + db_username = "example" |
| 11 | + |
| 12 | + # aws dms describe-event-categories |
| 13 | + replication_instance_event_categories = ["failure", "creation", "deletion", "maintenance", "failover", "low storage", "configuration change"] |
| 14 | + replication_task_event_categories = ["failure", "state change", "creation", "deletion", "configuration change"] |
| 15 | + |
| 16 | + tags = { |
| 17 | + Example = local.name |
| 18 | + Environment = "dev" |
| 19 | + } |
| 20 | +} |
| 21 | + |
| 22 | +data "aws_region" "current" {} |
| 23 | + |
| 24 | +################################################################################ |
| 25 | +# Supporting Resources |
| 26 | +################################################################################ |
| 27 | + |
| 28 | +module "vpc" { |
| 29 | + source = "terraform-aws-modules/vpc/aws" |
| 30 | + version = "~> 3" |
| 31 | + |
| 32 | + name = local.name |
| 33 | + cidr = "10.99.0.0/18" |
| 34 | + |
| 35 | + azs = ["${local.region}a", "${local.region}b", "${local.region}d"] # careful on which AZs support DMS VPC endpoint |
| 36 | + public_subnets = ["10.99.0.0/24", "10.99.1.0/24", "10.99.2.0/24"] |
| 37 | + private_subnets = ["10.99.3.0/24", "10.99.4.0/24", "10.99.5.0/24"] |
| 38 | + database_subnets = ["10.99.7.0/24", "10.99.8.0/24", "10.99.9.0/24"] |
| 39 | + |
| 40 | + create_database_subnet_group = true |
| 41 | + enable_nat_gateway = false # not required, using private VPC endpoint |
| 42 | + single_nat_gateway = false |
| 43 | + |
| 44 | + enable_dhcp_options = true |
| 45 | + enable_dns_hostnames = true |
| 46 | + dhcp_options_domain_name = data.aws_region.current.name == "us-east-1" ? "ec2.internal" : "${data.aws_region.current.name}.compute.internal" |
| 47 | + |
| 48 | + tags = local.tags |
| 49 | +} |
| 50 | + |
| 51 | +module "vpc_endpoints" { |
| 52 | + source = "terraform-aws-modules/vpc/aws//modules/vpc-endpoints" |
| 53 | + version = "~> 3" |
| 54 | + |
| 55 | + vpc_id = module.vpc.vpc_id |
| 56 | + security_group_ids = [module.vpc_endpoint_security_group.security_group_id] |
| 57 | + |
| 58 | + endpoints = { |
| 59 | + dms = { |
| 60 | + service = "dms" |
| 61 | + private_dns_enabled = true |
| 62 | + subnet_ids = module.vpc.database_subnets |
| 63 | + tags = { Name = "dms-vpc-endpoint" } |
| 64 | + } |
| 65 | + } |
| 66 | + |
| 67 | + tags = local.tags |
| 68 | +} |
| 69 | + |
| 70 | +module "vpc_endpoint_security_group" { |
| 71 | + source = "terraform-aws-modules/security-group/aws" |
| 72 | + version = "~> 4" |
| 73 | + |
| 74 | + name = "${local.name}-vpc-endpoint" |
| 75 | + description = "Security group for VPC endpoints" |
| 76 | + vpc_id = module.vpc.vpc_id |
| 77 | + |
| 78 | + ingress_with_cidr_blocks = [ |
| 79 | + { |
| 80 | + from_port = 443 |
| 81 | + to_port = 443 |
| 82 | + protocol = "tcp" |
| 83 | + description = "VPC Endpoints HTTPs for the VPC CIDR" |
| 84 | + cidr_blocks = module.vpc.vpc_cidr_block |
| 85 | + } |
| 86 | + ] |
| 87 | + |
| 88 | + egress_cidr_blocks = [module.vpc.vpc_cidr_block] |
| 89 | + egress_rules = ["all-all"] |
| 90 | + |
| 91 | + tags = local.tags |
| 92 | +} |
| 93 | + |
| 94 | +module "security_group" { |
| 95 | + source = "terraform-aws-modules/security-group/aws" |
| 96 | + version = "~> 4" |
| 97 | + |
| 98 | + # Creates multiple |
| 99 | + for_each = { |
| 100 | + source = ["postgresql-tcp"] |
| 101 | + destination = ["mysql-tcp"] |
| 102 | + replication-instance = ["postgresql-tcp", "mysql-tcp"] |
| 103 | + } |
| 104 | + |
| 105 | + name = "${local.name}-${each.key}" |
| 106 | + description = "Security group for ${each.key}" |
| 107 | + vpc_id = module.vpc.vpc_id |
| 108 | + |
| 109 | + ingress_cidr_blocks = module.vpc.database_subnets_cidr_blocks |
| 110 | + ingress_rules = each.value |
| 111 | + |
| 112 | + egress_cidr_blocks = [module.vpc.vpc_cidr_block] |
| 113 | + egress_rules = ["all-all"] |
| 114 | + |
| 115 | + tags = local.tags |
| 116 | +} |
| 117 | + |
| 118 | +module "rds_aurora" { |
| 119 | + source = "terraform-aws-modules/rds-aurora/aws" |
| 120 | + version = "~> 5" |
| 121 | + |
| 122 | + # Creates multiple |
| 123 | + for_each = { |
| 124 | + source = { |
| 125 | + engine = "aurora-postgresql" |
| 126 | + engine_version = "11.12" |
| 127 | + }, |
| 128 | + destination = { |
| 129 | + engine = "aurora-mysql" |
| 130 | + engine_version = "5.7.mysql_aurora.2.07.5" |
| 131 | + } |
| 132 | + } |
| 133 | + |
| 134 | + name = "${local.name}-${each.key}" |
| 135 | + database_name = local.db_name |
| 136 | + username = local.db_username |
| 137 | + apply_immediately = true |
| 138 | + |
| 139 | + engine = each.value.engine |
| 140 | + engine_version = each.value.engine_version |
| 141 | + replica_count = 1 |
| 142 | + instance_type = "db.t3.medium" |
| 143 | + storage_encrypted = false |
| 144 | + skip_final_snapshot = true |
| 145 | + |
| 146 | + vpc_id = module.vpc.vpc_id |
| 147 | + subnets = module.vpc.database_subnets |
| 148 | + db_subnet_group_name = module.vpc.database_subnet_group_name |
| 149 | + create_security_group = false |
| 150 | + vpc_security_group_ids = [module.security_group[each.key].security_group_id] |
| 151 | + |
| 152 | + tags = local.tags |
| 153 | +} |
| 154 | + |
| 155 | +resource "aws_sns_topic" "example" { |
| 156 | + name = local.name |
| 157 | +} |
| 158 | + |
| 159 | +################################################################################ |
| 160 | +# DMS Module |
| 161 | +################################################################################ |
| 162 | + |
| 163 | +module "dms_disabled" { |
| 164 | + source = "../.." |
| 165 | + |
| 166 | + create = false |
| 167 | +} |
| 168 | + |
| 169 | +module "dms_default" { |
| 170 | + source = "../.." |
| 171 | + |
| 172 | + # Note - if enabled, this will by default only create |
| 173 | + # - DMS necessary IAM roles |
| 174 | + # - Subnet group |
| 175 | + # - Replication instance |
| 176 | + create = false # not enabling by default to avoid messing with the IAM roles |
| 177 | + |
| 178 | + # Subnet group |
| 179 | + repl_subnet_group_name = local.name |
| 180 | + repl_subnet_group_description = "DMS Subnet group for ${local.name}" |
| 181 | + repl_subnet_group_subnet_ids = module.vpc.database_subnets |
| 182 | + |
| 183 | + # Instance |
| 184 | + repl_instance_class = "dms.t3.large" |
| 185 | + repl_instance_id = local.name |
| 186 | + |
| 187 | + tags = local.tags |
| 188 | +} |
| 189 | + |
| 190 | +module "dms_aurora_postgresql_aurora_mysql" { |
| 191 | + source = "../.." |
| 192 | + |
| 193 | + # Subnet group |
| 194 | + repl_subnet_group_name = local.name |
| 195 | + repl_subnet_group_description = "DMS Subnet group for ${local.name}" |
| 196 | + repl_subnet_group_subnet_ids = module.vpc.database_subnets |
| 197 | + |
| 198 | + # Instance |
| 199 | + repl_instance_allocated_storage = 64 |
| 200 | + repl_instance_auto_minor_version_upgrade = true |
| 201 | + repl_instance_allow_major_version_upgrade = true |
| 202 | + repl_instance_apply_immediately = true |
| 203 | + repl_instance_engine_version = "3.4.5" |
| 204 | + repl_instance_multi_az = true |
| 205 | + repl_instance_preferred_maintenance_window = "sun:10:30-sun:14:30" |
| 206 | + repl_instance_publicly_accessible = false |
| 207 | + repl_instance_class = "dms.t3.large" |
| 208 | + repl_instance_id = local.name |
| 209 | + repl_instance_vpc_security_group_ids = [module.security_group["replication-instance"].security_group_id] |
| 210 | + |
| 211 | + endpoints = { |
| 212 | + source = { |
| 213 | + database_name = local.db_name |
| 214 | + endpoint_id = "${local.name}-source" |
| 215 | + endpoint_type = "source" |
| 216 | + engine_name = "aurora-postgresql" |
| 217 | + extra_connection_attributes = "heartbeatFrequency=1;" |
| 218 | + username = local.db_username |
| 219 | + password = module.rds_aurora["source"].rds_cluster_master_password |
| 220 | + port = 5432 |
| 221 | + server_name = module.rds_aurora["source"].rds_cluster_endpoint |
| 222 | + ssl_mode = "none" |
| 223 | + tags = { EndpointType = "source" } |
| 224 | + } |
| 225 | + |
| 226 | + destination = { |
| 227 | + database_name = local.db_name |
| 228 | + endpoint_id = "${local.name}-destination" |
| 229 | + endpoint_type = "target" |
| 230 | + engine_name = "aurora" |
| 231 | + extra_connection_attributes = "" |
| 232 | + username = local.db_username |
| 233 | + password = module.rds_aurora["destination"].rds_cluster_master_password |
| 234 | + port = 3306 |
| 235 | + server_name = module.rds_aurora["destination"].rds_cluster_endpoint |
| 236 | + ssl_mode = "none" |
| 237 | + tags = { EndpointType = "destination" } |
| 238 | + } |
| 239 | + } |
| 240 | + |
| 241 | + replication_tasks = { |
| 242 | + cdc_ex = { |
| 243 | + replication_task_id = "${local.name}-cdc" |
| 244 | + migration_type = "cdc" |
| 245 | + replication_task_settings = file("task_settings.json") |
| 246 | + table_mappings = file("table_mappings.json") |
| 247 | + source_endpoint_key = "source" |
| 248 | + target_endpoint_key = "destination" |
| 249 | + tags = { Task = "PostgreSQL-to-MySQL" } |
| 250 | + } |
| 251 | + } |
| 252 | + |
| 253 | + event_subscriptions = { |
| 254 | + # # Despite what the terraform docs say, this is not valid - you must supply a `source_type` |
| 255 | + # all = { |
| 256 | + # name = "all-events" |
| 257 | + # enabled = true |
| 258 | + # instance_event_subscription_keys = [local.name] |
| 259 | + # task_event_subscription_keys = ["cdc_ex"] |
| 260 | + # event_categories = distinct(concat(local.replication_instance_event_categories, local.replication_task_event_categories)) |
| 261 | + # sns_topic_arn = aws_sns_topic.example.arn |
| 262 | + # }, |
| 263 | + instance = { |
| 264 | + name = "instance-events" |
| 265 | + enabled = true |
| 266 | + instance_event_subscription_keys = [local.name] |
| 267 | + source_type = "replication-instance" |
| 268 | + event_categories = local.replication_instance_event_categories |
| 269 | + sns_topic_arn = aws_sns_topic.example.arn |
| 270 | + } |
| 271 | + task = { |
| 272 | + name = "task-events" |
| 273 | + enabled = true |
| 274 | + task_event_subscription_keys = ["cdc_ex"] |
| 275 | + source_type = "replication-task" |
| 276 | + event_categories = local.replication_task_event_categories |
| 277 | + sns_topic_arn = aws_sns_topic.example.arn |
| 278 | + } |
| 279 | + } |
| 280 | + |
| 281 | + # # Not applicable in this example but demonstrating its use |
| 282 | + # certificates = { |
| 283 | + # source = { |
| 284 | + # certificate_id = "${local.name}-source" |
| 285 | + # certificate_pem = "..." |
| 286 | + # } |
| 287 | + # destination = { |
| 288 | + # certificate_id = "${local.name}-destination" |
| 289 | + # certificate_pem = "..." |
| 290 | + # } |
| 291 | + # } |
| 292 | + |
| 293 | + tags = local.tags |
| 294 | +} |
0 commit comments