Building function package separately fails with Terraform v1.13
Description
When we deploy multiple functions with the same source code, we use a separate module call for the function packaging before deploying the functions from the generated package zip (see example code below). This worked fine previously, with Terraform v1.12.2, but no longer works with Terraform v1.13 (just released).
This appears to be because Terraform now checks whether the zip file exists during the plan step (it doesn't yet), and then expects the same result during the apply step (but the file does exist at that stage). This validation has been added in Terraform v1.13 - see hashicorp/terraform#37001.
Is this an intended way to use this module, or should we have each function module call do its own packaging of the same code? I seem to remember that this may have caused a problem in the past with parallel builds overwriting each other (as they were building from exactly the same source directory with the same hash).
- [x] β I have searched the open/closed issues and my issue is not listed.
Versions
-
Module version [Required]: v8.1.0
-
Terraform version: v1.13.0
-
Provider version(s):
provider registry.terraform.io/hashicorp/aws v6.10.0 provider registry.terraform.io/hashicorp/external v2.3.5 provider registry.terraform.io/hashicorp/local v2.5.3 provider registry.terraform.io/hashicorp/null v3.2.4
Reproduction Code
module "lambda_package" {
source = "terraform-aws-modules/lambda/aws"
create_function = false
source_path = "src"
}
module "lambda_function_1" {
source = "terraform-aws-modules/lambda/aws"
create_package = false
function_name = "function_1"
handler = "index.handler_1"
runtime = "python3.13"
local_existing_package = module.lambda_package.local_filename
}
module "lambda_function_2" {
source = "terraform-aws-modules/lambda/aws"
create_package = false
function_name = "function_2"
handler = "index.handler_2"
runtime = "python3.13"
local_existing_package = module.lambda_package.local_filename
}
Steps to reproduce the behavior:
- terraform init
- terraform apply
Expected behavior
- terraform apply completes successfully
Actual behavior
...
Plan: 10 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
module.lambda_package.local_file.archive_plan[0]: Creating...
module.lambda_package.local_file.archive_plan[0]: Creation complete after 0s [id=f1bd1c8263437ce6362e0088149d446474d01b4b]
module.lambda_package.null_resource.archive[0]: Creating...
module.lambda_package.null_resource.archive[0]: Provisioning with 'local-exec'...
module.lambda_package.null_resource.archive[0] (local-exec): local-exec: Executing: Suppressed by quiet=true
module.lambda_package.null_resource.archive[0] (local-exec): zip: creating 'builds/44141140bf260a18b95b6fa11487ff73afdc0d31a7b36c4149fb66efdb35d648.zip' archive
module.lambda_package.null_resource.archive[0] (local-exec): zip: adding content of directory: /Users/richard.owen/Desktop/lambda_test/src
module.lambda_package.null_resource.archive[0] (local-exec): zip: adding: index.py
module.lambda_package.null_resource.archive[0] (local-exec): Created: builds/44141140bf260a18b95b6fa11487ff73afdc0d31a7b36c4149fb66efdb35d648.zip
module.lambda_package.null_resource.archive[0]: Creation complete after 0s [id=475881427651737073]
module.lambda_function_1.aws_cloudwatch_log_group.lambda[0]: Creating...
module.lambda_function_2.aws_cloudwatch_log_group.lambda[0]: Creating...
module.lambda_function_2.aws_iam_role.lambda[0]: Creating...
module.lambda_function_1.aws_iam_role.lambda[0]: Creating...
module.lambda_function_1.aws_cloudwatch_log_group.lambda[0]: Creation complete after 0s [id=/aws/lambda/function_1]
module.lambda_function_2.aws_cloudwatch_log_group.lambda[0]: Creation complete after 0s [id=/aws/lambda/function_2]
module.lambda_function_1.data.aws_iam_policy_document.logs[0]: Reading...
module.lambda_function_2.data.aws_iam_policy_document.logs[0]: Reading...
module.lambda_function_2.data.aws_iam_policy_document.logs[0]: Read complete after 0s [id=932321896]
module.lambda_function_1.data.aws_iam_policy_document.logs[0]: Read complete after 0s [id=4263703753]
module.lambda_function_2.aws_iam_role.lambda[0]: Creation complete after 1s [id=function_2]
module.lambda_function_2.aws_iam_role_policy.logs[0]: Creating...
module.lambda_function_1.aws_iam_role.lambda[0]: Creation complete after 1s [id=function_1]
module.lambda_function_1.aws_iam_role_policy.logs[0]: Creating...
module.lambda_function_2.aws_iam_role_policy.logs[0]: Creation complete after 0s [id=function_2:function_2-logs]
module.lambda_function_1.aws_iam_role_policy.logs[0]: Creation complete after 0s [id=function_1:function_1-logs]
β·
β Error: Error in function call
β
β on .terraform/modules/lambda_function_1/main.tf line 15, in locals:
β 15: was_missing = var.local_existing_package != null ? !fileexists(var.local_existing_package) : local.archive_was_missing
β βββββββββββββββββ
β β while calling fileexists(path)
β β var.local_existing_package is "builds/44141140bf260a18b95b6fa11487ff73afdc0d31a7b36c4149fb66efdb35d648.zip"
β
β Call to function "fileexists" failed: function returned an inconsistent result.
β΅
β·
β Error: Error in function call
β
β on .terraform/modules/lambda_function_2/main.tf line 15, in locals:
β 15: was_missing = var.local_existing_package != null ? !fileexists(var.local_existing_package) : local.archive_was_missing
β βββββββββββββββββ
β β while calling fileexists(path)
β β var.local_existing_package is "builds/44141140bf260a18b95b6fa11487ff73afdc0d31a7b36c4149fb66efdb35d648.zip"
β
β Call to function "fileexists" failed: function returned an inconsistent result.
β΅
Interesting... I don't have a specific fix in mind for this issue, but I think you are right that Terraform 1.13 suddenly became more strict with filesystem functions.
As a workaround, you can try to split the runs (terraform apply -target=module.lambda_package) to get the package before using it in other modules.
This issue has been automatically marked as stale because it has been open 30 days with no activity. Remove stale label or comment or this issue will be closed in 10 days
Not stale
This issue has been automatically marked as stale because it has been open 30 days with no activity. Remove stale label or comment or this issue will be closed in 10 days
Not stale
Came here to report this also. Thanks for beating me to it @richardowen !
I traced through the commit history to try and better understand the use case for local.was_missing, but it goes all the way back to the very first commit! π
If we look at how it is used, the only reference is to the source_code_hash. But I think that's a "nice to have". We could instead impose on the user the requirement to change some other attribute to update the function. Like changing the filename when the package changes. Which the module already does, by writing the hash as the filename. Code changes, new filename, new package, lambda is updated.
Basically, perhaps when the user provides var.local_existing_package, we just short-circuit local.was_missing to avoid the call to fileexists() and also force source_code_hash = null?
@antonbabenko Do you think this proposal would be acceptable?
I traced through the commit history to try and better understand the use case for
local.was_missing, but it goes all the way back to the very first commit! πIf we look at how it is used, the only reference is to the
source_code_hash. But I think that's a "nice to have". We could instead impose on the user the requirement to change some other attribute to update the function. Like changing the filename when the package changes. Which the module already does, by writing the hash as the filename. Code changes, new filename, new package, lambda is updated.Basically, perhaps when the user provides
var.local_existing_package, we just short-circuitlocal.was_missingto avoid the call tofileexists()and also forcesource_code_hash = null?
This issue has been automatically marked as stale because it has been open 30 days with no activity. Remove stale label or comment or this issue will be closed in 10 days
Not stale