diff --git a/README.md b/README.md index ed9599d..91cf90b 100644 --- a/README.md +++ b/README.md @@ -296,6 +296,7 @@ Tasks are the "jobs" that perform the necessary actions of migrating from `sourc Examples codified under the [`examples`](https://github.com/terraform-aws-modules/terraform-aws-dms/tree/master/examples) are intended to give users references for how to use the module(s) as well as testing/validating changes to the source code of the module. If contributing to the project, please be sure to make any appropriate updates to the relevant examples to allow maintainers to test your changes and to keep the examples up to date for users. Thank you! - [Complete](https://github.com/terraform-aws-modules/terraform-aws-dms/tree/master/examples/complete) +- [Serverless](https://github.com/terraform-aws-modules/terraform-aws-dms/tree/master/examples/serverless) ## Requirements @@ -303,14 +304,14 @@ Examples codified under the [`examples`](https://github.com/terraform-aws-module | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.31 | +| [aws](#requirement\_aws) | >= 5.32 | | [time](#requirement\_time) | >= 0.9 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.31 | +| [aws](#provider\_aws) | >= 5.32 | | [time](#provider\_time) | >= 0.9 | ## Modules @@ -324,6 +325,7 @@ No modules. | [aws_dms_certificate.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dms_certificate) | resource | | [aws_dms_endpoint.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dms_endpoint) | resource | | [aws_dms_event_subscription.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dms_event_subscription) | resource | +| [aws_dms_replication_config.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dms_replication_config) | resource | | [aws_dms_replication_instance.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dms_replication_instance) | resource | | [aws_dms_replication_subnet_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dms_replication_subnet_group) | resource | | [aws_dms_replication_task.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dms_replication_task) | resource | @@ -368,6 +370,7 @@ No modules. | [create\_access\_iam\_role](#input\_create\_access\_iam\_role) | Determines whether the ECS task definition IAM role should be created | `bool` | `true` | no | | [create\_access\_policy](#input\_create\_access\_policy) | Determines whether the IAM policy should be created | `bool` | `true` | no | | [create\_iam\_roles](#input\_create\_iam\_roles) | Determines whether the required [DMS IAM resources](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Security.html#CHAP_Security.APIRole) will be created | `bool` | `true` | no | +| [create\_repl\_instance](#input\_create\_repl\_instance) | Indicates whether a replication instace should be created | `bool` | `true` | no | | [create\_repl\_subnet\_group](#input\_create\_repl\_subnet\_group) | Determines whether the replication subnet group will be created | `bool` | `true` | no | | [enable\_redshift\_target\_permissions](#input\_enable\_redshift\_target\_permissions) | Determines whether `redshift.amazonaws.com` is permitted access to assume the `dms-access-for-endpoint` role | `bool` | `false` | no | | [endpoints](#input\_endpoints) | Map of objects that define the endpoints to be created | `any` | `{}` | no | @@ -426,6 +429,7 @@ No modules. | [replication\_subnet\_group\_id](#output\_replication\_subnet\_group\_id) | The ID of the subnet group | | [replication\_tasks](#output\_replication\_tasks) | A map of maps containing the replication tasks created and their full output of attributes and values | | [s3\_endpoints](#output\_s3\_endpoints) | A map of maps containing the S3 endpoints created and their full output of attributes and values | +| [serverless\_replication\_tasks](#output\_serverless\_replication\_tasks) | A map of maps containing the serverless replication tasks (replication\_config) created and their full output of attributes and values | ## License diff --git a/examples/README.md b/examples/README.md index 2f8fb61..5917bc2 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,3 +1,4 @@ # Terraform AWS DMS examples - [Complete](https://github.com/terraform-aws-modules/terraform-aws-dms/tree/master/examples/complete) +- [Serverless](https://github.com/terraform-aws-modules/terraform-aws-dms/tree/master/examples/serverless) diff --git a/examples/serverless/README.md b/examples/serverless/README.md new file mode 100644 index 0000000..20ee554 --- /dev/null +++ b/examples/serverless/README.md @@ -0,0 +1,81 @@ +# Serverless AWS DMS Example + +Configuration in this directory creates: + +- AWS IAM roles [necessary for AWS DMS](https://aws.amazon.com/premiumsupport/knowledge-center/dms-redshift-connectivity-failures/) +- [AWS DMS subnet group](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_ReplicationInstance.VPC.html) +- [AWS DMS serverless replication configuration](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Serverless.html) +- Two [AWS DMS replication endpoints](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Endpoints.Creating.html) - one `source` and one `target` to migrate data from an Aurora PostgreSQL cluster to Aurora MySQL cluster +- Necessary supporting resources to demonstrate the capabilities of the module (VPC, Aurora clusters, security groups, etc.) + +## Usage + +To run this example you need to execute: + +```bash +$ terraform init +$ terraform plan +$ terraform apply +``` + +Note that this example may create resources which will incur monetary charges on your AWS bill. Run `terraform destroy` when you no longer need these resources. + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 5.32 | +| [random](#requirement\_random) | >= 3.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | >= 5.32 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [dms\_aurora\_postgresql\_aurora\_mysql](#module\_dms\_aurora\_postgresql\_aurora\_mysql) | ../.. | n/a | +| [rds\_aurora](#module\_rds\_aurora) | terraform-aws-modules/rds-aurora/aws | ~> 8.0 | +| [secrets\_manager\_mysql](#module\_secrets\_manager\_mysql) | terraform-aws-modules/secrets-manager/aws | ~> 1.0 | +| [secrets\_manager\_postgresql](#module\_secrets\_manager\_postgresql) | terraform-aws-modules/secrets-manager/aws | ~> 1.0 | +| [security\_group](#module\_security\_group) | terraform-aws-modules/security-group/aws | ~> 5.0 | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | +| [vpc\_endpoints](#module\_vpc\_endpoints) | terraform-aws-modules/vpc/aws//modules/vpc-endpoints | ~> 5.0 | + +## Resources + +| Name | Type | +|------|------| +| [aws_kms_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | +| [aws_rds_cluster_parameter_group.postgresql](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group) | resource | +| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | + +## Inputs + +No inputs. + +## Outputs + +| Name | Description | +|------|-------------| +| [dms\_access\_for\_endpoint\_iam\_role\_arn](#output\_dms\_access\_for\_endpoint\_iam\_role\_arn) | Amazon Resource Name (ARN) specifying the role | +| [dms\_access\_for\_endpoint\_iam\_role\_id](#output\_dms\_access\_for\_endpoint\_iam\_role\_id) | Name of the IAM role | +| [dms\_access\_for\_endpoint\_iam\_role\_unique\_id](#output\_dms\_access\_for\_endpoint\_iam\_role\_unique\_id) | Stable and unique string identifying the role | +| [dms\_cloudwatch\_logs\_iam\_role\_arn](#output\_dms\_cloudwatch\_logs\_iam\_role\_arn) | Amazon Resource Name (ARN) specifying the role | +| [dms\_cloudwatch\_logs\_iam\_role\_id](#output\_dms\_cloudwatch\_logs\_iam\_role\_id) | Name of the IAM role | +| [dms\_cloudwatch\_logs\_iam\_role\_unique\_id](#output\_dms\_cloudwatch\_logs\_iam\_role\_unique\_id) | Stable and unique string identifying the role | +| [dms\_vpc\_iam\_role\_arn](#output\_dms\_vpc\_iam\_role\_arn) | Amazon Resource Name (ARN) specifying the role | +| [dms\_vpc\_iam\_role\_id](#output\_dms\_vpc\_iam\_role\_id) | Name of the IAM role | +| [dms\_vpc\_iam\_role\_unique\_id](#output\_dms\_vpc\_iam\_role\_unique\_id) | Stable and unique string identifying the role | +| [endpoints](#output\_endpoints) | A map of maps containing the endpoints created and their full output of attributes and values | +| [replication\_subnet\_group\_id](#output\_replication\_subnet\_group\_id) | The ID of the subnet group | +| [s3\_endpoints](#output\_s3\_endpoints) | A map of maps containing the S3 endpoints created and their full output of attributes and values | +| [serverless\_replication\_tasks](#output\_serverless\_replication\_tasks) | A map of maps containing the serverless replication tasks created and their full output of attributes and values | + + +Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-dms/blob/master/LICENSE). diff --git a/examples/serverless/configs/table_mappings.json b/examples/serverless/configs/table_mappings.json new file mode 100644 index 0000000..96c0cdf --- /dev/null +++ b/examples/serverless/configs/table_mappings.json @@ -0,0 +1,12 @@ +{ + "rules": [{ + "rule-type": "selection", + "rule-id": "1", + "rule-name": "1", + "object-locator": { + "schema-name": "%", + "table-name": "%" + }, + "rule-action": "include" + }] +} diff --git a/examples/serverless/configs/task_settings.json b/examples/serverless/configs/task_settings.json new file mode 100644 index 0000000..904c3da --- /dev/null +++ b/examples/serverless/configs/task_settings.json @@ -0,0 +1,68 @@ +{ + "TargetMetadata": { + "SupportLobs": true, + "FullLobMode": false, + "LobChunkSize": 64, + "LimitedSizeLobMode": true, + "LobMaxSize": 32, + "BatchApplyEnabled": true + }, + "FullLoadSettings": { + "TargetTablePrepMode": "DO_NOTHING", + "CreatePkAfterFullLoad": false, + "StopTaskCachedChangesApplied": false, + "StopTaskCachedChangesNotApplied": false, + "MaxFullLoadSubTasks": 8, + "TransactionConsistencyTimeout": 600, + "CommitRate": 10000 + }, + "Logging": { + "EnableLogging": true + }, + "ControlTablesSettings": { + "HistoryTimeslotInMinutes": 5, + "HistoryTableEnabled": false, + "SuspendedTablesTableEnabled": false, + "StatusTableEnabled": false + }, + "StreamBufferSettings": { + "StreamBufferCount": 3, + "StreamBufferSizeInMB": 8 + }, + "ChangeProcessingTuning": { + "BatchApplyPreserveTransaction": true, + "BatchApplyTimeoutMin": 1, + "BatchApplyTimeoutMax": 30, + "BatchApplyMemoryLimit": 500, + "BatchSplitSize": 0, + "MinTransactionSize": 1000, + "CommitTimeout": 1, + "MemoryLimitTotal": 1024, + "MemoryKeepTime": 60, + "StatementCacheSize": 50 + }, + "ChangeProcessingDdlHandlingPolicy": { + "HandleSourceTableDropped": true, + "HandleSourceTableTruncated": true, + "HandleSourceTableAltered": true + }, + "ErrorBehavior": { + "DataErrorPolicy": "LOG_ERROR", + "DataTruncationErrorPolicy": "LOG_ERROR", + "DataErrorEscalationPolicy": "SUSPEND_TABLE", + "DataErrorEscalationCount": 50, + "TableErrorPolicy": "SUSPEND_TABLE", + "TableErrorEscalationPolicy": "STOP_TASK", + "TableErrorEscalationCount": 50, + "RecoverableErrorCount": 0, + "RecoverableErrorInterval": 5, + "RecoverableErrorThrottling": true, + "RecoverableErrorThrottlingMax": 1800, + "ApplyErrorDeletePolicy": "IGNORE_RECORD", + "ApplyErrorInsertPolicy": "LOG_ERROR", + "ApplyErrorUpdatePolicy": "LOG_ERROR", + "ApplyErrorEscalationPolicy": "LOG_ERROR", + "ApplyErrorEscalationCount": 0, + "FullLoadIgnoreConflicts": true + } +} diff --git a/examples/serverless/main.tf b/examples/serverless/main.tf new file mode 100644 index 0000000..2da1b85 --- /dev/null +++ b/examples/serverless/main.tf @@ -0,0 +1,284 @@ +provider "aws" { + region = local.region +} + +data "aws_availability_zones" "available" {} + +locals { + region = "us-east-1" + name = "dms-ex-${basename(path.cwd)}" + + vpc_cidr = "10.0.0.0/16" + azs = slice(data.aws_availability_zones.available.names, 0, 3) + + db_name = "example" + db_username = "example" + db_password = "password123!" # do better! + + tags = { + Name = local.name + Example = local.name + Repository = "https://github.com/terraform-aws-modules/terraform-aws-dms" + } +} + +################################################################################ +# DMS Module +################################################################################ + +module "dms_aurora_postgresql_aurora_mysql" { + source = "../.." + + # Subnet group + repl_subnet_group_name = local.name + repl_subnet_group_description = "DMS Subnet group for ${local.name}" + repl_subnet_group_subnet_ids = module.vpc.private_subnets + + # Instance + create_repl_instance = false + + # Access role + create_access_iam_role = true + access_secret_arns = [ + module.secrets_manager_postgresql.secret_arn, + module.secrets_manager_mysql.secret_arn, + ] + + # Endpoints + endpoints = { + postgresql-source = { + database_name = local.db_name + endpoint_id = "${local.name}-postgresql-source" + endpoint_type = "source" + engine_name = "aurora-postgresql" + extra_connection_attributes = "heartbeatFrequency=1;secretsManagerEndpointOverride=${module.vpc_endpoints.endpoints["secretsmanager"]["dns_entry"][0]["dns_name"]}" + secrets_manager_arn = module.secrets_manager_postgresql.secret_arn + + postgres_settings = { + capture_ddls = false + heartbeat_enable = true + heartbeat_frequency = 1 + } + + tags = { EndpointType = "postgresql-source" } + } + + mysql-destination = { + database_name = local.db_name + endpoint_id = "${local.name}-mysql-destination" + endpoint_type = "target" + engine_name = "aurora" + extra_connection_attributes = "secretsManagerEndpointOverride=${module.vpc_endpoints.endpoints["secretsmanager"]["dns_entry"][0]["dns_name"]}" + secrets_manager_arn = module.secrets_manager_mysql.secret_arn + + tags = { EndpointType = "mysql-destination" } + } + } + + replication_tasks = { + postgresql_mysql = { + replication_task_id = "postgresql-to-mysql" + migration_type = "full-load-and-cdc" + replication_task_settings = file("configs/task_settings.json") + table_mappings = file("configs/table_mappings.json") + source_endpoint_key = "postgresql-source" + target_endpoint_key = "mysql-destination" + + serverless_config = { + max_capacity_units = 2 + min_capacity_units = 1 + multi_az = true + vpc_security_group_ids = [module.security_group["replication-configuration"].security_group_id] + } + + tags = { Task = "PostgreSQL-to-MySQL" } + } + } + + tags = local.tags +} + +################################################################################ +# Supporting Resources +################################################################################ + +module "vpc" { + source = "terraform-aws-modules/vpc/aws" + version = "~> 5.0" + + name = local.name + cidr = local.vpc_cidr + + azs = local.azs + public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)] + private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 3)] + database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 6)] + + enable_nat_gateway = true + single_nat_gateway = true + + create_database_subnet_group = true + + tags = local.tags +} + +module "vpc_endpoints" { + source = "terraform-aws-modules/vpc/aws//modules/vpc-endpoints" + version = "~> 5.0" + + vpc_id = module.vpc.vpc_id + create_security_group = true + security_group_name_prefix = "${local.name}-vpc-endpoints-" + security_group_description = "VPC endpoint security group" + security_group_rules = { + ingress_https = { + description = "HTTPS from VPC" + cidr_blocks = [module.vpc.vpc_cidr_block] + } + } + + endpoints = { + secretsmanager = { + service_name = "com.amazonaws.${local.region}.secretsmanager" + subnet_ids = module.vpc.private_subnets + } + } + + tags = local.tags +} + +module "security_group" { + source = "terraform-aws-modules/security-group/aws" + version = "~> 5.0" + + # Creates multiple + for_each = { + postgresql-source = ["postgresql-tcp"] + mysql-destination = ["mysql-tcp"] + replication-configuration = ["postgresql-tcp", "mysql-tcp"] + } + + name = "${local.name}-${each.key}" + description = "Security group for ${each.key}" + vpc_id = module.vpc.vpc_id + + ingress_cidr_blocks = [module.vpc.vpc_cidr_block] + ingress_rules = each.value + + egress_cidr_blocks = ["0.0.0.0/0"] + egress_rules = ["all-all"] + + tags = local.tags +} + +resource "aws_rds_cluster_parameter_group" "postgresql" { + name = "${local.name}-postgresql" + family = "aurora-postgresql14" + + parameter { + name = "rds.logical_replication" + value = 1 + apply_method = "pending-reboot" + } + + parameter { + name = "wal_sender_timeout" + value = 0 + } + + tags = local.tags +} + +module "rds_aurora" { + source = "terraform-aws-modules/rds-aurora/aws" + version = "~> 8.0" + + # Creates multiple + for_each = { + postgresql-source = { + engine = "aurora-postgresql" + engine_version = "14.7" + enabled_cloudwatch_logs_exports = ["postgresql"] + }, + mysql-destination = { + engine = "aurora-mysql" + engine_version = "8.0" + enabled_cloudwatch_logs_exports = ["general", "error", "slowquery"] + } + } + + name = "${local.name}-${each.key}" + database_name = local.db_name + master_username = local.db_username + master_password = local.db_password + manage_master_user_password = false + apply_immediately = true + + engine = each.value.engine + engine_version = each.value.engine_version + instance_class = "db.t3.medium" + instances = { 1 = {}, 2 = {} } + storage_encrypted = true + skip_final_snapshot = true + db_cluster_parameter_group_name = each.key == "postgresql-source" ? aws_rds_cluster_parameter_group.postgresql.id : null + + vpc_id = module.vpc.vpc_id + subnets = module.vpc.database_subnets + db_subnet_group_name = module.vpc.database_subnet_group_name + create_db_subnet_group = false + create_security_group = false + vpc_security_group_ids = [module.security_group[each.key].security_group_id] + + tags = local.tags +} + +resource "aws_kms_key" "this" { + description = "KMS CMK for ${local.name}" + enable_key_rotation = true + + tags = local.tags +} + +module "secrets_manager_postgresql" { + source = "terraform-aws-modules/secrets-manager/aws" + version = "~> 1.0" + + name_prefix = "PostgreSQL-${local.name}-" + description = "Secret for ${local.name}" + + # Secret + recovery_window_in_days = 0 + secret_string = jsonencode( + { + username = local.db_username + password = local.db_password + port = 5432 + host = module.rds_aurora["postgresql-source"].cluster_endpoint + } + ) + kms_key_id = aws_kms_key.this.id + + tags = local.tags +} + +module "secrets_manager_mysql" { + source = "terraform-aws-modules/secrets-manager/aws" + version = "~> 1.0" + + name_prefix = "MySQL-${local.name}-" + description = "Secret for ${local.name}" + + # Secret + recovery_window_in_days = 0 + secret_string = jsonencode( + { + username = local.db_username + password = local.db_password + port = 3306 + host = module.rds_aurora["mysql-destination"].cluster_endpoint + } + ) + kms_key_id = aws_kms_key.this.id + + tags = local.tags +} diff --git a/examples/serverless/outputs.tf b/examples/serverless/outputs.tf new file mode 100644 index 0000000..4ef9343 --- /dev/null +++ b/examples/serverless/outputs.tf @@ -0,0 +1,89 @@ +################################################################################ +# IAM Roles +################################################################################ + +# DMS Endpoint +output "dms_access_for_endpoint_iam_role_arn" { + description = "Amazon Resource Name (ARN) specifying the role" + value = module.dms_aurora_postgresql_aurora_mysql.dms_access_for_endpoint_iam_role_arn +} + +output "dms_access_for_endpoint_iam_role_id" { + description = "Name of the IAM role" + value = module.dms_aurora_postgresql_aurora_mysql.dms_access_for_endpoint_iam_role_id +} + +output "dms_access_for_endpoint_iam_role_unique_id" { + description = "Stable and unique string identifying the role" + value = module.dms_aurora_postgresql_aurora_mysql.dms_access_for_endpoint_iam_role_unique_id +} + +# DMS CloudWatch Logs +output "dms_cloudwatch_logs_iam_role_arn" { + description = "Amazon Resource Name (ARN) specifying the role" + value = module.dms_aurora_postgresql_aurora_mysql.dms_cloudwatch_logs_iam_role_arn +} + +output "dms_cloudwatch_logs_iam_role_id" { + description = "Name of the IAM role" + value = module.dms_aurora_postgresql_aurora_mysql.dms_cloudwatch_logs_iam_role_id +} + +output "dms_cloudwatch_logs_iam_role_unique_id" { + description = "Stable and unique string identifying the role" + value = module.dms_aurora_postgresql_aurora_mysql.dms_cloudwatch_logs_iam_role_unique_id +} + +# DMS VPC +output "dms_vpc_iam_role_arn" { + description = "Amazon Resource Name (ARN) specifying the role" + value = module.dms_aurora_postgresql_aurora_mysql.dms_vpc_iam_role_arn +} + +output "dms_vpc_iam_role_id" { + description = "Name of the IAM role" + value = module.dms_aurora_postgresql_aurora_mysql.dms_vpc_iam_role_id +} + +output "dms_vpc_iam_role_unique_id" { + description = "Stable and unique string identifying the role" + value = module.dms_aurora_postgresql_aurora_mysql.dms_vpc_iam_role_unique_id +} + +################################################################################ +# Subnet group +################################################################################ + +output "replication_subnet_group_id" { + description = "The ID of the subnet group" + value = module.dms_aurora_postgresql_aurora_mysql.replication_subnet_group_id +} + +################################################################################ +# Endpoint +################################################################################ + +output "endpoints" { + description = "A map of maps containing the endpoints created and their full output of attributes and values" + value = module.dms_aurora_postgresql_aurora_mysql.endpoints + sensitive = true +} + +################################################################################ +# S3 Endpoint +################################################################################ + +output "s3_endpoints" { + description = "A map of maps containing the S3 endpoints created and their full output of attributes and values" + value = module.dms_aurora_postgresql_aurora_mysql.s3_endpoints + sensitive = true +} + +################################################################################ +# Replication Task +################################################################################ + +output "serverless_replication_tasks" { + description = "A map of maps containing the serverless replication tasks created and their full output of attributes and values" + value = module.dms_aurora_postgresql_aurora_mysql.serverless_replication_tasks +} diff --git a/examples/serverless/variables.tf b/examples/serverless/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/examples/serverless/versions.tf b/examples/serverless/versions.tf new file mode 100644 index 0000000..facfe7d --- /dev/null +++ b/examples/serverless/versions.tf @@ -0,0 +1,14 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + random = { + source = "hashicorp/random" + version = ">= 3.0" + } + } +} diff --git a/main.tf b/main.tf index 452f970..012113e 100644 --- a/main.tf +++ b/main.tf @@ -139,7 +139,7 @@ resource "aws_dms_replication_subnet_group" "this" { ################################################################################ resource "aws_dms_replication_instance" "this" { - count = var.create ? 1 : 0 + count = var.create && var.create_repl_instance ? 1 : 0 allocated_storage = var.repl_instance_allocated_storage allow_major_version_upgrade = var.repl_instance_allow_major_version_upgrade @@ -380,11 +380,11 @@ resource "aws_dms_s3_endpoint" "this" { } ################################################################################ -# Replication Task +# Replication Task - Instance ################################################################################ resource "aws_dms_replication_task" "this" { - for_each = { for k, v in var.replication_tasks : k => v if var.create } + for_each = { for k, v in var.replication_tasks : k => v if var.create && !contains(keys(v), "serverless_config") } cdc_start_position = try(each.value.cdc_start_position, null) cdc_start_time = try(each.value.cdc_start_time, null) @@ -400,6 +400,41 @@ resource "aws_dms_replication_task" "this" { tags = merge(var.tags, try(each.value.tags, {})) } +################################################################################ +# Replication Task - Serverless +################################################################################ +resource "aws_dms_replication_config" "this" { + for_each = { for k, v in var.replication_tasks : k => v if var.create && contains(keys(v), "serverless_config") } + + replication_config_identifier = each.value.replication_task_id + resource_identifier = each.value.replication_task_id + + replication_type = each.value.migration_type + source_endpoint_arn = try(aws_dms_endpoint.this[each.value.source_endpoint_key].endpoint_arn, aws_dms_s3_endpoint.this[each.value.source_endpoint_key].endpoint_arn) + target_endpoint_arn = try(aws_dms_endpoint.this[each.value.target_endpoint_key].endpoint_arn, aws_dms_s3_endpoint.this[each.value.target_endpoint_key].endpoint_arn) + table_mappings = try(each.value.table_mappings, null) + + replication_settings = try(each.value.replication_task_settings, null) + supplemental_settings = try(each.value.supplemental_task_settings, null) + + start_replication = try(each.value.start_replication_task, null) + + compute_config { + availability_zone = try(each.value.serverless_config.availability_zone, null) + dns_name_servers = try(each.value.serverless_config.dns_name_servers, null) + kms_key_id = try(each.value.serverless_config.kms_key_id, null) + max_capacity_units = each.value.serverless_config.max_capacity_units + min_capacity_units = try(each.value.serverless_config.min_capacity_units, null) + multi_az = try(each.value.serverless_config.multi_az, null) + preferred_maintenance_window = try(each.value.serverless_config.preferred_maintenance_window, null) + replication_subnet_group_id = local.subnet_group_id + vpc_security_group_ids = try(each.value.serverless_config.vpc_security_group_ids, null) + } + + tags = merge(var.tags, try(each.value.tags, {})) +} + + ################################################################################ # Event Subscription ################################################################################ diff --git a/outputs.tf b/outputs.tf index 05cfad3..b005f61 100644 --- a/outputs.tf +++ b/outputs.tf @@ -112,6 +112,11 @@ output "replication_tasks" { value = aws_dms_replication_task.this } +output "serverless_replication_tasks" { + description = "A map of maps containing the serverless replication tasks (replication_config) created and their full output of attributes and values" + value = aws_dms_replication_config.this +} + ################################################################################ # Event Subscription ################################################################################ diff --git a/variables.tf b/variables.tf index d020262..f470b8e 100644 --- a/variables.tf +++ b/variables.tf @@ -78,6 +78,12 @@ variable "repl_subnet_group_tags" { # Instance ################################################################################ +variable "create_repl_instance" { + description = "Indicates whether a replication instace should be created" + type = bool + default = true +} + variable "repl_instance_allocated_storage" { description = "The amount of storage (in gigabytes) to be initially allocated for the replication instance. Min: 5, Max: 6144, Default: 50" type = number diff --git a/versions.tf b/versions.tf index 32ed5b5..446b9fb 100644 --- a/versions.tf +++ b/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.31" + version = ">= 5.32" } time = { source = "hashicorp/time"