Skip to content

Commit

Permalink
UML-3114 Use global DynamoDB tables (#2365)
Browse files Browse the repository at this point in the history
* UML-3114 Use global DynamoDB tables
  • Loading branch information
Sam Ainsworth authored Oct 16, 2023
1 parent 8b2e943 commit e617e18
Show file tree
Hide file tree
Showing 11 changed files with 222 additions and 49 deletions.
135 changes: 116 additions & 19 deletions terraform/environment/dynamodb.tf
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
resource "aws_dynamodb_table" "actor_codes_table" {
name = "${local.environment_name}-${local.environment.dynamodb_tables.actor_codes.name}"
billing_mode = "PAY_PER_REQUEST"
hash_key = "ActorCode"
name = "${local.environment_name}-${local.environment.dynamodb_tables.actor_codes.name}"
billing_mode = "PAY_PER_REQUEST"
hash_key = "ActorCode"
stream_enabled = true
stream_view_type = "NEW_AND_OLD_IMAGES"
server_side_encryption {
enabled = true
}
Expand All @@ -15,15 +17,34 @@ resource "aws_dynamodb_table" "actor_codes_table" {
enabled = true
}

# For each region in the environment that is not the primary_region, create a DynamoDB replica.

dynamic "replica" {
for_each = [
for region in local.environment.regions : region
if region.is_primary != true
]

content {
region_name = replica.value.name
propagate_tags = true

}
}

lifecycle {
prevent_destroy = false
}

provider = aws.eu_west_1
}

resource "aws_dynamodb_table" "stats_table" {
name = "${local.environment_name}-${local.environment.dynamodb_tables.stats.name}"
billing_mode = "PAY_PER_REQUEST"
hash_key = "TimePeriod"
name = "${local.environment_name}-${local.environment.dynamodb_tables.stats.name}"
billing_mode = "PAY_PER_REQUEST"
hash_key = "TimePeriod"
stream_enabled = true
stream_view_type = "NEW_AND_OLD_IMAGES"
#tfsec:ignore:aws-dynamodb-table-customer-key - same as the other tables. Will update in one go as separate ticket
server_side_encryption {
enabled = true
Expand All @@ -38,15 +59,31 @@ resource "aws_dynamodb_table" "stats_table" {
enabled = true
}

dynamic "replica" {
for_each = [
for region in local.environment.regions : region
if region.is_primary != true
]

content {
region_name = replica.value.name
propagate_tags = true
}
}

lifecycle {
prevent_destroy = false
}

provider = aws.eu_west_1
}

resource "aws_dynamodb_table" "actor_users_table" {
name = "${local.environment_name}-${local.environment.dynamodb_tables.actor_users.name}"
billing_mode = "PAY_PER_REQUEST"
hash_key = "Id"
name = "${local.environment_name}-${local.environment.dynamodb_tables.actor_users.name}"
billing_mode = "PAY_PER_REQUEST"
hash_key = "Id"
stream_enabled = true
stream_view_type = "NEW_AND_OLD_IMAGES"
server_side_encryption {
enabled = true
}
Expand Down Expand Up @@ -111,16 +148,31 @@ resource "aws_dynamodb_table" "actor_users_table" {
enabled = true
}

dynamic "replica" {
for_each = [
for region in local.environment.regions : region
if region.is_primary != true
]

content {
region_name = replica.value.name
propagate_tags = true
}
}

lifecycle {
prevent_destroy = false
}

provider = aws.eu_west_1
}

resource "aws_dynamodb_table" "viewer_codes_table" {
name = "${local.environment_name}-${local.environment.dynamodb_tables.viewer_codes.name}"
billing_mode = "PAY_PER_REQUEST"
hash_key = "ViewerCode"
name = "${local.environment_name}-${local.environment.dynamodb_tables.viewer_codes.name}"
billing_mode = "PAY_PER_REQUEST"
hash_key = "ViewerCode"
stream_enabled = true
stream_view_type = "NEW_AND_OLD_IMAGES"
server_side_encryption {
enabled = true
}
Expand Down Expand Up @@ -151,17 +203,33 @@ resource "aws_dynamodb_table" "viewer_codes_table" {
enabled = true
}

dynamic "replica" {
for_each = [
for region in local.environment.regions : region
if region.is_primary != true
]

content {
region_name = replica.value.name
propagate_tags = true
}
}


lifecycle {
prevent_destroy = false
}

provider = aws.eu_west_1
}

resource "aws_dynamodb_table" "viewer_activity_table" {
name = "${local.environment_name}-${local.environment.dynamodb_tables.viewer_activity.name}"
billing_mode = "PAY_PER_REQUEST"
hash_key = "ViewerCode"
range_key = "Viewed"
name = "${local.environment_name}-${local.environment.dynamodb_tables.viewer_activity.name}"
billing_mode = "PAY_PER_REQUEST"
hash_key = "ViewerCode"
range_key = "Viewed"
stream_enabled = true
stream_view_type = "NEW_AND_OLD_IMAGES"
server_side_encryption {
enabled = true
}
Expand All @@ -179,16 +247,32 @@ resource "aws_dynamodb_table" "viewer_activity_table" {
enabled = true
}

dynamic "replica" {
for_each = [
for region in local.environment.regions : region
if region.is_primary != true
]

content {
region_name = replica.value.name
propagate_tags = true
}
}


lifecycle {
prevent_destroy = false
}

provider = aws.eu_west_1
}

resource "aws_dynamodb_table" "user_lpa_actor_map" {
name = "${local.environment_name}-${local.environment.dynamodb_tables.user_lpa_actor_map.name}"
billing_mode = "PAY_PER_REQUEST"
hash_key = "Id"
name = "${local.environment_name}-${local.environment.dynamodb_tables.user_lpa_actor_map.name}"
billing_mode = "PAY_PER_REQUEST"
hash_key = "Id"
stream_enabled = true
stream_view_type = "NEW_AND_OLD_IMAGES"
server_side_encryption {
enabled = true
}
Expand Down Expand Up @@ -240,8 +324,21 @@ resource "aws_dynamodb_table" "user_lpa_actor_map" {
enabled = true
}

dynamic "replica" {
for_each = [
for region in local.environment.regions : region
if region.is_primary != true
]

content {
region_name = replica.value.name
propagate_tags = true
}
}

lifecycle {
prevent_destroy = false
}

provider = aws.eu_west_1
}
9 changes: 8 additions & 1 deletion terraform/environment/locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,14 @@ variable "environments" {
stats = object({
name = string
})
})
}),
regions = map(
object({
name = string
is_active = bool
is_primary = bool
})
)
})
)
}
Expand Down
2 changes: 1 addition & 1 deletion terraform/environment/region.tf
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ module "eu_west_1" {
parameter_store_arns = [aws_ssm_parameter.system_message_view_en.arn, aws_ssm_parameter.system_message_view_cy.arn, aws_ssm_parameter.system_message_use_en.arn, aws_ssm_parameter.system_message_use_cy.arn]
pdf_container_version = local.environment.pdf_container_version
public_access_enabled = var.public_access_enabled
regions = local.environment.regions
session_expires_use = local.environment.session_expires_use
session_expires_view = local.environment.session_expires_view
session_expiry_warning = local.environment.session_expiry_warning
Expand Down Expand Up @@ -73,7 +74,6 @@ module "eu_west_1" {
"viewer" = aws_route53_record.viewer_use_my_lpa.fqdn
}


providers = {
aws.region = aws.eu_west_1
aws.management = aws.management
Expand Down
2 changes: 1 addition & 1 deletion terraform/environment/region/actor_ecs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ resource "aws_ecs_service" "actor" {
name = "actor-service"
cluster = aws_ecs_cluster.use_an_lpa.id
task_definition = aws_ecs_task_definition.actor.arn
desired_count = var.autoscaling.use.minimum
desired_count = local.use_desired_count
platform_version = "1.4.0"

network_configuration {
Expand Down
22 changes: 11 additions & 11 deletions terraform/environment/region/admin_ecs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ resource "aws_ecs_service" "admin" {
name = "admin-service"
cluster = aws_ecs_cluster.use_an_lpa.id
task_definition = aws_ecs_task_definition.admin.arn
desired_count = 1
desired_count = local.admin_desired_count
platform_version = "1.4.0"

network_configuration {
Expand Down Expand Up @@ -165,16 +165,16 @@ data "aws_iam_policy_document" "admin_permissions_role" {
]

resources = [
var.dynamodb_tables.actor_users_table.arn,
"${var.dynamodb_tables.actor_users_table.arn}/index/*",
var.dynamodb_tables.viewer_codes_table.arn,
"${var.dynamodb_tables.viewer_codes_table.arn}/index/*",
var.dynamodb_tables.viewer_activity_table.arn,
"${var.dynamodb_tables.viewer_activity_table.arn}/index/*",
var.dynamodb_tables.user_lpa_actor_map.arn,
"${var.dynamodb_tables.user_lpa_actor_map.arn}/index/*",
var.dynamodb_tables.stats_table.arn,
"${var.dynamodb_tables.stats_table.arn}/index/*",
local.dynamodb_tables_arns.actor_users_table_arn,
"${local.dynamodb_tables_arns.actor_users_table_arn}/index/*",
local.dynamodb_tables_arns.viewer_codes_table_arn,
"${local.dynamodb_tables_arns.viewer_codes_table_arn}/index/*",
local.dynamodb_tables_arns.viewer_activity_table_arn,
"${local.dynamodb_tables_arns.viewer_activity_table_arn}/index/*",
local.dynamodb_tables_arns.user_lpa_actor_map_arn,
"${local.dynamodb_tables_arns.user_lpa_actor_map_arn}/index/*",
local.dynamodb_tables_arns.stats_table_arn,
"${local.dynamodb_tables_arns.stats_table_arn}/index/*",
]
}

Expand Down
26 changes: 13 additions & 13 deletions terraform/environment/region/api_ecs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ resource "aws_ecs_service" "api" {
name = "api-service"
cluster = aws_ecs_cluster.use_an_lpa.id
task_definition = aws_ecs_task_definition.api.arn
desired_count = var.autoscaling.api.minimum
desired_count = local.api_desired_count
platform_version = "1.4.0"
health_check_grace_period_seconds = 0

Expand Down Expand Up @@ -193,18 +193,18 @@ data "aws_iam_policy_document" "api_permissions_role" {
]

resources = [
var.dynamodb_tables.actor_codes_table.arn,
"${var.dynamodb_tables.actor_codes_table.arn}/index/*",
var.dynamodb_tables.actor_users_table.arn,
"${var.dynamodb_tables.actor_users_table.arn}/index/*",
var.dynamodb_tables.viewer_codes_table.arn,
"${var.dynamodb_tables.viewer_codes_table.arn}/index/*",
var.dynamodb_tables.viewer_activity_table.arn,
"${var.dynamodb_tables.viewer_activity_table.arn}/index/*",
var.dynamodb_tables.user_lpa_actor_map.arn,
"${var.dynamodb_tables.user_lpa_actor_map.arn}/index/*",
var.dynamodb_tables.stats_table.arn,
"${var.dynamodb_tables.stats_table.arn}/index/*",
local.dynamodb_tables_arns.actor_codes_table_arn,
"${local.dynamodb_tables_arns.actor_codes_table_arn}/index/*",
local.dynamodb_tables_arns.actor_users_table_arn,
"${local.dynamodb_tables_arns.actor_users_table_arn}/index/*",
local.dynamodb_tables_arns.viewer_codes_table_arn,
"${local.dynamodb_tables_arns.viewer_codes_table_arn}/index/*",
local.dynamodb_tables_arns.viewer_activity_table_arn,
"${local.dynamodb_tables_arns.viewer_activity_table_arn}/index/*",
local.dynamodb_tables_arns.user_lpa_actor_map_arn,
"${local.dynamodb_tables_arns.user_lpa_actor_map_arn}/index/*",
local.dynamodb_tables_arns.stats_table_arn,
"${local.dynamodb_tables_arns.stats_table_arn}/index/*",
]
}

Expand Down
25 changes: 24 additions & 1 deletion terraform/environment/region/locals.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
locals {
policy_region_prefix = lower(replace(data.aws_region.current.name, "-", ""))
}

# The primary region is the region where the DynamoDB tables are created and replicated to the secondary region.
primary_region = keys({ for region, region_data in var.regions : region => region_data if region_data.is_primary })[0]
is_primary_region = local.primary_region == data.aws_region.current.name ? true : false
is_active_region = var.regions[data.aws_region.current.name].is_active

# Desired count of the ECS services. Only an active region will have a desired count greater than 0.
use_desired_count = local.is_active_region ? var.autoscaling.use.minimum : 0
pdf_desired_count = local.is_active_region ? var.autoscaling.pdf.minimum : 0
view_desired_count = local.is_active_region ? var.autoscaling.view.minimum : 0
api_desired_count = local.is_active_region ? var.autoscaling.api.minimum : 0
admin_desired_count = local.is_active_region ? 1 : 0

# Replace the region in the ARN of the DynamoDB tables with the region of the current stack as the tables are created in the primary region
# and replicated to the secondary region. This allows use to grant access to the tables in the secondary region for applications running in the secondary region.
dynamodb_tables_arns = {
actor_codes_table_arn = replace(var.dynamodb_tables.actor_codes_table.arn, local.primary_region, data.aws_region.current.name)
stats_table_arn = replace(var.dynamodb_tables.stats_table.arn, local.primary_region, data.aws_region.current.name)
actor_users_table_arn = replace(var.dynamodb_tables.actor_users_table.arn, local.primary_region, data.aws_region.current.name)
viewer_codes_table_arn = replace(var.dynamodb_tables.viewer_codes_table.arn, local.primary_region, data.aws_region.current.name)
viewer_activity_table_arn = replace(var.dynamodb_tables.viewer_activity_table.arn, local.primary_region, data.aws_region.current.name)
user_lpa_actor_map_arn = replace(var.dynamodb_tables.user_lpa_actor_map.arn, local.primary_region, data.aws_region.current.name)
}
}
2 changes: 1 addition & 1 deletion terraform/environment/region/pdf_ecs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ resource "aws_ecs_service" "pdf" {
name = "pdf-service"
cluster = aws_ecs_cluster.use_an_lpa.id
task_definition = aws_ecs_task_definition.pdf.arn
desired_count = var.autoscaling.pdf.minimum
desired_count = local.pdf_desired_count
platform_version = "1.4.0"

network_configuration {
Expand Down
13 changes: 13 additions & 0 deletions terraform/environment/region/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,19 @@ variable "public_access_enabled" {
default = false
}

variable "regions" {
description = "Information about which regions are being used"
type = map(object({
is_primary = bool
is_active = bool
}))

validation {
condition = length([for region in keys(var.regions) : region if var.regions[region].is_primary]) == 1
error_message = "One (and only one) region must be marked as primary"
}
}

variable "route_53_fqdns" {
description = "The FQDNs to use for the Route 53 records."

Expand Down
Loading

0 comments on commit e617e18

Please sign in to comment.