Cyclic dependency terraform
Asked Answered
D

2

5

I have a cyclic dependency problem with terraform. I have a user pool user_pool which invokes a lambda user_signup_lambda as a trigger when a user signs up. This lambda also needs the user pool's Id as an environment variable.

My terraform looks like this

resource "aws_lambda_function" "user_signup_lambda" {
  function_name = "user_signup_lambda"
  filename = var.file_name
  source_code_hash = filebase64sha256(var.file_name)
  handler = var.handler
  runtime = var.runtime
  memory_size = var.memory_size
  timeout = var.timeout
  role = var.iam_role_arn

  environment {
    variables = aws_cognito_user_pool.user_pool.id
  }
}

resource "aws_cognito_user_pool" "user_pool" {
  name = "some-user-pool"

  ....other config

  lambda_config {
     post_confirmation = module.user_signup_lambda.arn
  }

This results in the following error:

Error: Cycle: module.user_signup_lambda.var.environment_variables, module.user_signup_lambda.aws_lambda_function.lambda_function, module.user_signup_lambda.output.arn, aws_cognito_user_pool.user_pool

Is there anyway around this other than hardcoding the user pool id?

Dunker answered 8/6, 2020 at 11:59 Comment(4)
Why do you need the pass the user pool ID? The event object should already have the userPoolId in it that you can read from there instead. docs.aws.amazon.com/cognito/latest/developerguide/… has an example Lambda function and an example event input.Clothbound
You're right...I can do it this way. My bad! thanks! However is there a way around this problem anyway if it wasn't possible to get it from the request?Dunker
The issue is that there is a clear dependency both ways on these. If you separated the Lambda function and the Cognito user pool from each other so they were applied separately then you could do it by either hardcoding the ARN/ID of one into the other or looking the other up with data sources. There's not a way of doing it in the same apply though.Clothbound
I found this: integralist.co.uk/posts/cognito in the terraform example the author addresses the exact same issue we face.Soto
A
4

We had the exact same issue. We ended up passing a variable containing the UserPool Name to Both UserPool and Lambda trigger resources.

The lambda then fetches the Cognito user pool info from it's name.

This way there is no cycle dependency between those 2 resources.

# Module containing Cognito userPool
resource "aws_cognito_user_pool" "default" {

 ...
  # Triggers
  lambda_config {
    post_confirmation = module.cognito_post_confirmation.lambda_post_confirmation.arn
  }
  name = var.cognito_identity_pool_name
} 


module "cognito_post_confirmation" {
  source                     = "./triggers/post-confirmation"
  cognito_identity_pool_name = var.cognito_identity_pool_name
  ...
}
Asa answered 4/2, 2021 at 9:57 Comment(0)
G
2

Have you considered using the event payload? It looks like this.

    { 
      version: '1',
      userPoolId: 'ap-southeast-BLABLA',
    }

The event itself has the userPoolId. If you're using this, there is no need to have an environment variable.

This is how I have been handling this problem.

    const postConfirmationHanlder = async (event) => {
        const userPoolId = event.userPoolId
        const userAttributes = event.request.userAttributes;
        const username = event.userName;
        // test of the logic
    }
Giraudoux answered 24/6, 2023 at 7:10 Comment(1)
This worked for me.Exhortation

© 2022 - 2024 — McMap. All rights reserved.