Skip to content

[Bug]: r/aws_lambda_invocation: Upgrade to v5.1.0 causes new invocation #40954

Closed
@jar-b

Description

Terraform Core Version

1.10.4

AWS Provider Version

5.83.0

Affected Resource(s)

  • aws_lambda_invocation

Expected Behavior

When updating an existing configuration from a provider version below v5.1.0, the upgrade process should not trigger a new invocation.

Actual Behavior

A new invocation is made after upgrading to a version >v5.1.0, even when the default lifecycle_scope of CREATE_ONLY is added.

Terraform Configuration Files

main.tf

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      # start with this version
      version = "4.20.0"

      # upgrade to anything after v5.1.0
      # version = "5.83.0"
    }
  }
}

provider "aws" {}

### Lambda function setup
data "aws_partition" "current" {}

data "aws_iam_policy_document" "test" {
  statement {
    effect  = "Allow"
    actions = ["sts:AssumeRole"]
    principals {
      type        = "Service"
      identifiers = ["lambda.${data.aws_partition.current.dns_suffix}"]
    }
  }
}

resource "aws_iam_role" "test" {
  name               = "jb-test-lambda-invocation"
  assume_role_policy = data.aws_iam_policy_document.test.json
}

resource "aws_iam_role_policy_attachment" "test" {
  policy_arn = "arn:${data.aws_partition.current.partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
  role       = aws_iam_role.test.name
}

resource "aws_lambda_function" "test" {
  depends_on = [aws_iam_role_policy_attachment.test]

  filename      = "lambda_function.zip"
  function_name = "jb-test"
  role          = aws_iam_role.test.arn
  handler       = "lambda_function.lambda_handler"
  runtime       = "python3.9"

  environment {
    variables = {
      TEST_DATA = "value3"
    }
  }
}
### End Lambda function setup

resource "aws_lambda_invocation" "example" {
  function_name = aws_lambda_function.test.function_name

  input = jsonencode({
    key1 = "value1"
    key2 = "value2"
  })
}

output "result_entry" {
  value = jsondecode(aws_lambda_invocation.example.result)
}

lambda_function.py

import json
import random

def lambda_handler(event, context):
    #Generate a random number
    random_number = random.randint(1,1000000)

    return {
        'statusCode': 200,
        'body': json.dumps({'random_number': random_number})
    }

Steps to Reproduce

  1. Provision the configuration above.
  2. Switch main.tf to the latest version of the AWS Terraform provider.
  3. Run terraform init -upgrade.
  4. Run terraform apply. The plan will display new arguments with default values being added to the aws_lambda_invocation resource. The apply itself will trigger a new invocation of the lambda function, despite the default lifecycle_scope of CREATE_ONLY.

Debug Output

Output after the initial apply (v4.20.0):

Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

Outputs:

result_entry = {
  "body" = "{\"random_number\": 770797}"
  "statusCode" = 200
}

First apply after upgrading to v5.83.0 (note the output initially indicates the result has not changed):

terraform apply -auto-approve
data.aws_partition.current: Reading...
data.aws_partition.current: Read complete after 0s [id=aws]
data.aws_iam_policy_document.test: Reading...
data.aws_iam_policy_document.test: Read complete after 0s [id=2690255455]
aws_iam_role.test: Refreshing state... [id=jb-test-lambda-invocation]
aws_iam_role_policy_attachment.test: Refreshing state... [id=jb-test-lambda-invocation-20250115194909810400000001]
aws_lambda_function.test: Refreshing state... [id=jb-test]
aws_lambda_invocation.example: Refreshing state... [id=jb-test_$LATEST_ff45cc3835165307ef414c23ca2c6f67]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # aws_lambda_invocation.example will be updated in-place
  ~ resource "aws_lambda_invocation" "example" {
        id              = "jb-test_$LATEST_ff45cc3835165307ef414c23ca2c6f67"
      + lifecycle_scope = "CREATE_ONLY"
      + terraform_key   = "tf"
        # (4 unchanged attributes hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.
aws_lambda_invocation.example: Modifying... [id=jb-test_$LATEST_ff45cc3835165307ef414c23ca2c6f67]
aws_lambda_invocation.example: Modifications complete after 0s [id=jb-test_$LATEST_ff45cc3835165307ef414c23ca2c6f67]

Apply complete! Resources: 0 added, 1 changed, 0 destroyed.

Outputs:

result_entry = {
  "body" = "{\"random_number\": 770797}"
  "statusCode" = 200
}

All subsequent plans show the result has changed, implying the upgrade invoked the function when it should not have.

terraform plan
data.aws_partition.current: Reading...
data.aws_partition.current: Read complete after 0s [id=aws]
data.aws_iam_policy_document.test: Reading...
data.aws_iam_policy_document.test: Read complete after 0s [id=2690255455]
aws_iam_role.test: Refreshing state... [id=jb-test-lambda-invocation]
aws_iam_role_policy_attachment.test: Refreshing state... [id=jb-test-lambda-invocation-20250115194909810400000001]
aws_lambda_function.test: Refreshing state... [id=jb-test]
aws_lambda_invocation.example: Refreshing state... [id=jb-test_$LATEST_ff45cc3835165307ef414c23ca2c6f67]

Changes to Outputs:
  ~ result_entry = {
      ~ body       = jsonencode(
          ~ {
              ~ random_number = 770797 -> 15568
            }
        )
        # (1 unchanged attribute hidden)
    }

You can apply this plan to save these new output values to the Terraform state, without changing any real infrastructure.

References

Would you like to implement a fix?

Yes

Metadata

Assignees

Labels

bugAddresses a defect in current functionality.service/lambdaIssues and PRs that pertain to the lambda service.

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions