This is a provider that can be helpful in implementing rolling rotations.
- Clone the repository
- Enter the repository directory
- Build the provider using the Go
installcommand:
$ go installThe flipflop provider helps implement zero-downtime rolling rotations in Terraform. It maintains two states (a and b) and tracks which one is currently active, allowing you to rotate resources gradually instead of all at once.
When you change the value input:
- The flipflop updates one output (
aorb) to match the new value - The other output remains unchanged (retains the old value)
- The
indexoutput indicates which is active (0 fora, 1 forb)
This enables you to create two instances of a resource and only invalidate one at a time.
resource "aws_iam_user" "example" {
name = "rotating-user"
}
resource "time_rotating" "rotation" {
rotation_days = 7
}
resource "flipflop" "rotation" {
value = time_rotating.rotation.id
}
# Create two access keys, one for each flipflop state
locals {
rotation_values = [flipflop.rotation.a, flipflop.rotation.b]
}
# Use null_resource to capture the rotation values as triggers
# This ensures the access keys are recreated when the flipflop values change
resource "null_resource" "rotation" {
count = length(local.rotation_values)
triggers = {
user = aws_iam_user.example.name
value = local.rotation_values[count.index]
}
}
resource "aws_iam_access_key" "rotation" {
count = length(local.rotation_values)
user = null_resource.rotation[count.index].triggers.user
lifecycle {
create_before_destroy = true
}
}
# Output the currently active access key
output "active_access_key_id" {
value = aws_iam_access_key.rotation[flipflop.rotation.index].id
}
output "active_secret_access_key" {
value = aws_iam_access_key.rotation[flipflop.rotation.index].secret
sensitive = true
}For more complex scenarios, encode all configuration through the flipflop
using jsonencode(). This ensures configuration changes also rotate gradually:
resource "flipflop" "config" {
value = jsonencode({
trigger = time_rotating.rotation.id
length = 32
special = true
})
}
locals {
configs = [
jsondecode(flipflop.config.a),
jsondecode(flipflop.config.b),
]
}
resource "random_password" "rotating" {
count = length(local.configs)
length = local.configs[count.index].length
special = local.configs[count.index].special
keepers = local.configs[count.index]
}
output "current_password" {
value = random_password.rotating[flipflop.config.index].result
sensitive = true
}See the examples/ directory for more detailed use cases including password rotation
and handling unknown values with the tri-state variant.
If you wish to work on the provider, you'll first need Go installed on your machine (see Requirements above).
To compile the provider, run go install. This will build the provider and put
the provider binary in the $GOPATH/bin directory.
To generate or update documentation, run go generate.
In order to run the full suite of Acceptance tests, run make testacc.
Note: Acceptance tests create real resources, and often cost money to run.
$ make testaccReleases are automatically created when commits are pushed to the main branch using semantic-release. Commit messages must follow the Conventional Commits format:
feat:- New feature (minor version bump)fix:- Bug fix (patch version bump)feat!:orBREAKING CHANGE:- Breaking change (major version bump)