Skip to content

Commit e755bd5

Browse files
committed
feat: Make the DynamoDB table optional for users of S3 state locking.
1 parent 6ee10ed commit e755bd5

4 files changed

Lines changed: 99 additions & 20 deletions

File tree

README.md

Lines changed: 70 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ to match your desired configuration. For example:
1515

1616
```hcl
1717
module "backend" {
18-
source = "github.com/codeforamerica/tofu-modules-aws-backend?ref=1.1.0"
18+
source = "github.com/codeforamerica/tofu-modules-aws-backend?ref=1.2.0"
1919
20-
project = "my-project"
21-
environment = "dev"
20+
project = "my-project"
21+
environment = "dev"
22+
create_dynamodb_table = true
2223
}
2324
```
2425

@@ -37,9 +38,10 @@ Add the backend configuration to your `main.tf` file:
3738
```hcl
3839
terraform {
3940
backend "s3" {
40-
bucket = "my-project-dev-tfstate"
41-
key = "my-project.tfstate" # Choose an appropriate key
42-
region = "us-east-1"
41+
bucket = "my-project-dev-tfstate"
42+
key = "my-project.tfstate" # Choose an appropriate key
43+
region = "us-east-1"
44+
dynamodb_table = "dev.tfstate"
4345
}
4446
}
4547
```
@@ -60,26 +62,78 @@ rm terraform.tfstate terraform.tfstate.backup
6062

6163
You now have a fully configured AWS backend for your project!
6264

65+
## Migrating from DynamoDB to S3 state locking
66+
67+
If you're currently using DynamoDB for state locking, you can migrate to [S3
68+
state locking][s3-locking] by updating your backend configuration to set
69+
`use_lockfile` to `true`.
70+
71+
```hcl
72+
terraform {
73+
backend "s3" {
74+
bucket = "my-project-dev-tfstate"
75+
key = "my-project.tfstate"
76+
region = "us-east-1"
77+
dynamodb_table = "dev.tfstate"
78+
use_lockfile = true # Add this line.
79+
}
80+
}
81+
```
82+
83+
You may choose to leave the `dynamodb_table` in place temporarily, which will
84+
use both mechanism for locking. This can be useful if you have workflows that
85+
haven't been updated to use state locking. See the [official
86+
documentation][s3-locking-migrate] for more details.
87+
88+
Once you've completely migrated to S3 state locking, you can remove
89+
`dynamodb_table` from your backend configuration.
90+
91+
### Destroying the DynamoDB table
92+
93+
Once you've completely migrated to S3 state locking, you can safely destroy the
94+
DynamoDB table. In order to do this, you must first set `force_delete` to `true`
95+
and apply the changes. This will disable deletion protection on the DynamoDB
96+
table.
97+
98+
Once applied, you can set `create_dynamodb_table` to `false` and apply the
99+
changes to destroy the DynamoDB table.
100+
101+
You can now set `force_delete` to `true` and apply the changes to re-enable
102+
deletion protection for other resources.
103+
63104
## Inputs
64105

65-
| Name | Description | Type | Default | Required |
66-
|--------------------------|------------------------------------------------------------------------------------------------------------|----------|---------|:--------:|
67-
| project | The name of the project. | `string` | n/a | yes |
68-
| bucket_suffix | Adds a random suffix to the bucket name to ensure its uniqueness. | `bool` | `false` | no |
69-
| environment | The environment for the project. | `string` | `"dev"` | no |
70-
| force_delete | Force delete resources on destroy. This must be set to true and applied before resources can be destroyed. | `bool` | `false` | no |
71-
| key_recovery_period | The number of days to retain the KMS key for recovery after deletion. | `number` | `30` | no |
72-
| state_version_expiration | Age (in days) before non-current versions of the state file are expired. | `number` | `30` | no |
73-
| tags | Optional tags to be applied to all resources. | `list` | `[]` | no |
106+
> [!WARNING]
107+
> The `create_dynamodb_table` input will default to `false` in the next major
108+
> version. If you're exclusively using [S3 state locking][s3-locking], you
109+
> should set this to `false` to avoid creating a DynamoDB table that you don't
110+
> need.
111+
>
112+
> If you're not currently using S3 state locking, we recommend you take the time
113+
> to [migrate][migrate-state-lock].
114+
115+
| Name | Description | Type | Default | Required |
116+
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | :------: |
117+
| project | The name of the project. | `string` | n/a | yes |
118+
| bucket_suffix | Adds a random suffix to the bucket name to ensure its uniqueness. | `bool` | `false` | no |
119+
| create_dynamodb_table | Whether to create a DynamoDB table to store the Terraform state lock. If you're exclusively using [S3 state locking][s3-locking], this is safe to disable. | `bool` | `true` | no |
120+
| environment | The environment for the project. | `string` | `"dev"` | no |
121+
| force_delete | Force delete resources on destroy. This must be set to true and applied before resources can be destroyed. | `bool` | `false` | no |
122+
| key_recovery_period | Recovery period for deleted KMS keys in days. Must be between `7` and `30`. | `number` | `30` | no |
123+
| state_version_expiration | Age (in days) before non-current versions of the state file are expired. | `number` | `30` | no |
124+
| tags | Optional tags to be applied to all resources. | `list` | `[]` | no |
74125

75126
## Outputs
76127

77128
| Name | Description | Type |
78-
|---------|------------------------------------------|----------|
129+
| ------- | ---------------------------------------- | -------- |
79130
| bucket | Name of the S3 bucket for state storage. | `string` |
80131
| kms_key | KMS key used to encrypt state. | `string` |
81132

82133
[badge-checks]: https://github.com/codeforamerica/tofu-modules-aws-backend/actions/workflows/main.yaml/badge.svg
83134
[badge-release]: https://img.shields.io/github/v/release/codeforamerica/tofu-modules-aws-backend?logo=github&label=Latest%20Release
84135
[code-checks]: https://github.com/codeforamerica/tofu-modules-aws-backend/actions/workflows/main.yaml
85136
[latest-release]: https://github.com/codeforamerica/tofu-modules-aws-backend/releases/latest
137+
[migrate-state-lock]: #migrating-from-dynamodb-to-s3-state-locking
138+
[s3-locking]: https://opentofu.org/docs/language/settings/backends/s3/#s3-state-locking
139+
[s3-locking-migrate]: https://opentofu.org/docs/language/settings/backends/s3/#migrating-from-dynamodb-to-s3-locking

main.tf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ resource "aws_kms_alias" "backend" {
2626
}
2727

2828
resource "aws_dynamodb_table" "tfstate_lock" {
29+
for_each = var.create_dynamodb_table ? toset(["this"]) : toset([])
30+
2931
name = "${var.environment}.tfstate"
3032
read_capacity = 1
3133
write_capacity = 1

moved.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
moved {
2+
from = aws_dynamodb_table.tfstate_lock
3+
to = aws_dynamodb_table.tfstate_lock["this"]
4+
}

variables.tf

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
11
variable "bucket_suffix" {
22
type = bool
3-
description = "Adds a random suffix to the bucket name to ensure its uniqueness."
3+
description = <<-EOT
4+
Adds a random suffix to the bucket name to ensure its uniqueness.
5+
EOT
46
default = false
57
}
68

9+
variable "create_dynamodb_table" {
10+
type = bool
11+
description = <<-EOT
12+
Whether to create a DynamoDB table to store the Terraform state lock. If
13+
you're exclusively using S3 state locking, this is safe to disable. This
14+
will default to `false` in the next major version.
15+
EOT
16+
default = true
17+
}
18+
719
variable "environment" {
820
type = string
921
default = "dev"
@@ -12,14 +24,19 @@ variable "environment" {
1224

1325
variable "force_delete" {
1426
type = bool
15-
description = "Force delete resources on destroy. This must be set to true and applied before resources can be destroyed."
27+
description = <<-EOT
28+
Force delete resources on destroy. This must be set to true and applied
29+
before resources can be destroyed.
30+
EOT
1631
default = false
1732
}
1833

1934
variable "key_recovery_period" {
2035
type = number
2136
default = 30
22-
description = "Recovery period for deleted KMS keys in days. Must be between 7 and 30."
37+
description = <<-EOT
38+
Recovery period for deleted KMS keys in days. Must be between `7` and `30`.
39+
EOT
2340

2441
validation {
2542
condition = var.key_recovery_period > 6 && var.key_recovery_period < 31
@@ -34,7 +51,9 @@ variable "project" {
3451

3552
variable "state_version_expiration" {
3653
type = number
37-
description = "Age (in days) before non-current versions of the state file are expired."
54+
description = <<-EOT
55+
Age (in days) before non-current versions of the state file are expired.
56+
EOT
3857
default = 30
3958
}
4059

0 commit comments

Comments
 (0)