I have been attempting to create an SFTP transfer workflow with multiple steps that I can change dynamically .
Error
With the below resource I get multiple workflows each with 5 steps. See below.
`
resource "aws_transfer_workflow" "Workflow" {
for_each = var.workflow_steps
dynamic "steps" {
for_each = each.value # To create a dynamic block
content {
dynamic "copy_step_details" {
for_each = each.value.type == "COPY" ? [1] : []
content {
name = each.value.name
source_file_location = each.value.source_file_location
destination_file_location {
s3_file_location {
bucket = each.value.destination_bucket
key = each.value.destination_key
}
}
}
}
dynamic "custom_step_details" {
for_each = each.value.type == "CUSTOM" ? [1] : []
content {
name = each.value.name
source_file_location = each.value.source_file_location
target = each.value.target
timeout_seconds = each.value.timeout_seconds
}
}
dynamic "delete_step_details" {
for_each = each.value.type == "DELETE" ? [1] : []
content {
name = each.value.name
source_file_location = each.value.source_file_location
}
}
dynamic "decrypt_step_details" {
for_each = each.value.type == "DECRYPT" ? [1] : []
content {
name = each.value.name
type = "PGP"
source_file_location = each.value.source_file_location
destination_file_location {
s3_file_location {
bucket = each.value.destination_bucket
key = each.value.destination_key
}
}
}
}
dynamic "tag_step_details" {
for_each = each.value.type == "TAG" ? [1] : []
content {
name = each.value.name
source_file_location = each.value.source_file_location
tags {
key = each.value.tag_key
value = each.value.tag_value
}
}
}
type = each.value.type
}
}
}
See variable used as input:
variable "workflow_steps" {
description = "Map of workflow steps"
type = map(object)
default = {
step1 = {
type = "COPY"
name = "Copy"
source_file_location = "$${original.file}"
destination_bucket = ""
destination_key = ""
}
step2 = {
type = "CUSTOM"
name = "Custom"
source_file_location = "$${original.file}"
target = "arn:aws:lambda"
timeout_seconds = 60
}
step3 = {
type = "TAG"
name = "Tag"
source_file_location = "$${original.file}"
tag_key = "Name"
tag_value = "Hello World"
}
step4 = {
type = "DECRYPT"
name = "Decrypt"
source_file_location = "$${original.file}"
destination_bucket = ""
destination_key = "test"
}
step5 = {
type = "DELETE"
name = "Delete"
source_file_location = "$${original.file}"
}
}
}
Result:
I attempted changing the variable data type but instead of getting 5 workflows with 5 steps I get 5 workflows with one step. When I attempt to remove the for_each block thats outside of the dynamic block the resource doesn't deploy successfully. I get further errors.
You should apply for_each only within the dynamic block to create multiple steps. The resource-level for_each should only be used if you're creating multiple workflows with different sets of steps.
Somthing like this, here count is just to test execution you can remove it if it's one workflow :
resource "aws_transfer_workflow" "workflow" {
count = 1 # Only one workflow
steps {
dynamic "step" {
for_each = var.workflow_steps
content {
type = step.value.type
dynamic "copy_step_details" {
for_each = step.value.type == "COPY" ? [1] : []
content {
name = step.value.name
source_file_location = step.value.source_file_location
destination_file_location {
s3_file_location {
bucket = step.value.destination_bucket
key = step.value.destination_key
}
}
}
}
dynamic "custom_step_details" {
for_each = step.value.type == "CUSTOM" ? [1] : []
content {
name = step.value.name
source_file_location = step.value.source_file_location
target = step.value.target
timeout_seconds = step.value.timeout_seconds
}
}
dynamic "delete_step_details" {
for_each = step.value.type == "DELETE" ? [1] : []
content {
name = step.value.name
source_file_location = step.value.source_file_location
}
}
dynamic "decrypt_step_details" {
for_each = step.value.type == "DECRYPT" ? [1] : []
content {
name = step.value.name
source_file_location = step.value.source_file_location
destination_file_location {
s3_file_location {
bucket = step.value.destination_bucket
key = step.value.destination_key
}
}
}
}
dynamic "tag_step_details" {
for_each = step.value.type == "TAG" ? [1] : []
content {
name = step.value.name
source_file_location = step.value.source_file_location
tags {
key = step.value.tag_key
value = step.value.tag_value
}
}
}
}
}
}
}