5

I designed an AWS codepipeline module using terraform module, I have multiple actual codepipelines using the codepipeline module. I use module as design pattern because all the codepipelines look similar, except that some of the codepipelines need approval stages, some do not need. How do I design the codepipeline module approval stages so that the actual codepipelines can be created based on different needs?

I tried to use count = 0 or 1 to control the stage but it does not work because the stage is not resource-level. Is there any tricky way or workaround?

I feel this link asked the similar question but I cannot figure out what is the answer: Terraform & AWS CodePipeline - Dynamically define actions on a stage

Here is my codepipeline terraform module:

resource "aws_codepipeline" "dev" {
  name     = "my_codepipeline"
  role_arn = ...
  ...
  stage {
    name = "Source"
    ...
  }
  stage {
    name = "test"
    ...
  }
  stage {
    # count = 0 # or 1. it does not work
    name = "Approval"
    action {
      name     = "Approval"
      owner    = "AWS"
      category = "Approval"
      provider = "Manual"
      version  = "1"

      configuration {
        NotificationArn    = "..."
        CustomData         = "..."
        ExternalEntityLink = "..."
      }
    }
  }
  stage {
    name = "prod"
    ...
  }
}

3 Answers 3

5

To dynamically add a stage (and not just an action) you could do the following:

dynamic "stage" {
   for_each = var.production_approval ? [1] : []
   content {
     name = "Approve"
     action {
       configuration = {
         NotificationArn = var.approve_sns_arn
         CustomData      = var.approve_comment
       }
       name     = "Production-Approval"
       category = "Approval"
       owner    = "AWS"
       provider = "Manual"
       version  = "1"
     }
   }
 }
Sign up to request clarification or add additional context in comments.

2 Comments

A link to the associated reference documents on this technic would strengthen your answer.
Is there a way to create 2 stages in one dynamic block
1

When going through your use case, I have the feeling that it is very suitable with new terraform feature in v0.12.x

Below is a sample on how to use for_each to set dynamic target regions, you should be fine to do the same for stages.

  dynamic "target_region" {
    for_each = var.target_image_regions
    content {
      name                   = target_region.value
      regional_replica_count = 1
    }
  }

let me know if this works for you or not.

Reference: https://www.hashicorp.com/blog/announcing-terraform-0-12

4 Comments

This answer would be improved with an example that directly solves the specific question rather than a generic for_each example.
Thanks @BMW. I guess I should set dynamic "approval_stage" {for each = var.enable_approval_stage", ...} and the content is like content {name = ..., action {approval's action} but I still do not understand how to control whether to create approval_stage or not create approval_stage. in which case approval_stage will not be created? Can you show me an example? Thanks,
these variables enable_approval_stage can be set via terraform variable dynamically, such as TF_VAR_enable_approval_stage=0 terraform apply So you can change these setting on-fly
Thanks @BMW, finally I decide not to control Approval stage. the AWS support said they do not have command to enable/disable a stage within a CodePipeline. so I do not believe terraform can set that either. I believe your approach works for other resource but not codepipeline. But Thank you very much for answering me.
1

I figured that you can get this working in Terraform 0.12+ as BMW said, but only if you have number of block greater than 0.

At least 1 "action" blocks are required.

Unfortunately, my (and your) use case required 0/1 actions depending on the environment so we have to manage it manually for a while.

Cheers.

dynamic "action" {
  for_each = local.production_approval # e.g. [] || [true]  
  content {
    category         = "Approval"
    configuration    = {}
    input_artifacts  = []
    name             = "Production-Approval"
    output_artifacts = []
    owner            = "AWS"
    provider         = "Manual"
    run_order        = 1
    version          = "1"
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.