Closed bpgould closed 1 year ago
Additional Context: I am wrapping in my own module. My module is defined like this:
variable "function_name" {
type = string
description = "The name of the Lambda function"
}
variable "description" {
type = string
description = "The description of the Lambda function"
}
variable "handler" {
type = string
description = "The handler function for the Lambda function"
}
variable "runtime" {
type = string
description = "The runtime for the Lambda function"
}
variable "s3_bucket_id" {
type = string
description = "The terraform id of the s3 bucket created outside of the module that will be used to store the Lambda deployment package artifacts"
}
variable "additional_iam_statements" {
type = list(object({
Sid = string
Effect = string
Action = list(string)
Resource = list(string)
}))
default = []
description = "Additional IAM statements to include in the Lambda function's policy"
}
variable "tags" {
type = map(string)
description = "The tags to apply to all resources created by the module"
default = {}
}
resource "aws_iam_policy" "lambda-policy" {
name = "${var.function_name}-policy"
description = "Allows Lambda function to execute"
policy = jsonencode({
Version = "2012-10-17"
Statement = concat(
[
{
Sid = "AllowLambdaToWriteLogs"
Action = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
]
Effect = "Allow"
Resource = "${aws_cloudwatch_log_group.lambda-log-group.arn}"
}
],
[for statement in var.additional_iam_statements : {
Sid = statement.Sid
Effect = statement.Effect
Action = statement.Action
Resource = statement.Resource
}]
)
})
}
resource "aws_iam_role" "lambda-role" {
name = "${var.function_name}-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
}
]
})
}
resource "aws_iam_role_policy_attachment" "lambda-policy-attachment" {
policy_arn = aws_iam_policy.lambda-policy.arn
role = aws_iam_role.lambda-role.name
}
resource "aws_cloudwatch_log_group" "lambda-log-group" {
name = "/aws/lambda/${var.function_name}"
}
module "lambda_function" {
source = "terraform-aws-modules/lambda/aws"
version = "4.13.0"
depends_on = [
aws_cloudwatch_log_group.lambda-log-group
]
function_name = var.function_name
description = var.description
handler = var.handler
runtime = var.runtime
publish = true
use_existing_cloudwatch_log_group = true
attach_cloudwatch_logs_policy = false
create_role = false
lambda_role = aws_iam_role.lambda-role.arn
source_path = "../lambdas/${var.function_name}/"
store_on_s3 = true
s3_bucket = var.s3_bucket_id
artifacts_dir = "builds/${var.function_name}/"
tags = var.tags
}
output "function_arn" {
value = module.lambda_function.lambda_function_arn
}
and I am using it like this:
module "lambda_function_bg" {
source = "../modules/bennett_lambda"
function_name = "add_user_to_jira"
handler = "main.lambda_handler"
runtime = "python3.9"
s3_bucket_id = aws_s3_bucket.uar-lambda-artifacts.id
description = "Lambda function for UAR to create a new user in Jira"
additional_iam_statements = [
{
Sid = "SSMParameterAccess"
Effect = "Allow"
Action = ["ssm:GetParameter"]
Resource = ["${aws_ssm_parameter.jira_token.arn}"]
},
{
Sid = "AllowUseOfSpecificCMK"
Effect = "Allow"
Action = [
"kms:Decrypt",
"kms:DescribeKey"
]
Resource = ["${aws_kms_key.parameter_store.arn}"]
}
]
}
and my directory structure is this:
I also manually aliased python3 to the absolute path of the 3.9 executable in case the module script was calling python via python3
and not python
. Still, same error.
I was just running into a similar issue when trying to run on Github actions. I ended up just needing to install python. But I think what may be going on here is that this module's package.py is actually looking for an executable on the path that matches the runtime exactly. So for example, if your runtime is python3.9
it's looking for python3.9
on the path, not python
or python3
. You can see it here, and command
is set to runtime
.
Try aliasing python3.9
to python3
or python
.
I was just running into a similar issue when trying to run on Github actions. I ended up just needing to install python. But I think what may be going on here is that this module's package.py is actually looking for an executable on the path that matches the runtime exactly. So for example, if your runtime is
python3.9
it's looking forpython3.9
on the path, notpython
orpython3
. You can see it here, andcommand
is set toruntime
.Try aliasing
python3.9
topython3
orpython
.
I created the alias alias python3.9="python"
and tested via python3.9 --version --> 3.9.10. Ran terraform apply
--> same error
Additional new information: The error comes from package.py line 684:
if not query.docker and not shutil.which(command):
shutiloutput = shutil.which(command)
raise RuntimeError(
"Python interpreter version equal "
"to defined lambda runtime ({}) should be "
"available in system PATH".format(command),
)
To troubleshoot, I changed it to:
if not query.docker and not shutil.which(command):
shutiloutput = shutil.which(command)
raise RuntimeError(
f"shutiloutput:{shutiloutput}",
"Python interpreter version equal "
"to defined lambda runtime ({}) should be "
"available in system PATH".format(command),
)
and I see that shutil.which()
returns None
So, I go to my terminal and do the following:
$ python -i
>>> import shutil
>>> shutil.which("python3.9")
>>> print(shutil.which("python3.9"))
None
>>> print(shutil.which("python"))
C:\Users\me\AppData\Local\Programs\Python\Python39\python.EXE
>>> print(shutil.which("python3"))
C:\Users\me\AppData\Local\Microsoft\WindowsApps\python3.EXE
>>> print(shutil.which("python3.9"))
None
OK, so it is explicit what the issue is, but if I rename the folder from `Python39` to `Python3.9` and update my PATH, it does not appear to be valid. Even when running `print(shutil.which("python3.9"))` Now I still get `None`
I'm not a windows guy, but I don't think it's based on the folder name but on the name of the executable. Try updating python.EXE
to python3.9.EXE
and make sure the folder containing that executable is on your path.
I'm not a windows guy, but I don't think it's based on the folder name but on the name of the executable. Try updating
python.EXE
topython3.9.EXE
and make sure the folder containing that executable is on your path.
It works! Woohoo, thank you!
I renamed the actual executable to python3.9.exe
and used the standard convention of adding the folder to my PATH.
This should be documented though because this is unusual behavior because the code uses shutil.which(runtime)
and in my example shutil.which("python3.9")
because of this, even an alias of alias python3.9="python"
will not work. I wonder if it would be more user friendly to use shutil.which("python")
then check that the version matches via subprocess command python --version
or some local python config file that I am not familiar with.
Thanks again!
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
Description
When running terraform plan or apply I get the following error:
I have spent a few days troubleshooting this issue, and I have tried the following methods. I am on Windows 11, using Git Bash, but I have also tried PowerShell.
I am using the python3.9 runtime and installed python 3.9.10 on my machine so that it would match - the python folder is python39 which should satisfy the requirement. I have manually added the executable to my System Environment Variable PATH and can confirm that it is accessible in PowerShell. I have manually added it to the PATH as well in my .bash_profile file and verified that it is accessible as well.
On both shells I type
python --version
and get back3.9.10
.I have deleted the .terraform folder, re-initialized, ran plan which worked, but always fails on
apply
.I have restarted my entire machine multiple times.
I have tried using virtual environments i.e. activate venv, check python version, then run
terraform apply
.I ran
terraform fmt
on all files.I set the DEBUG level to 3 using
export TF_LAMBDA_PACKAGE_LOG_LEVEL=DEBUG3
which yielded nothing interesting, but I was able to confirm that the paths make sense:
IMPORTANT NOTE: it works fine when
requirements.txt
is not present. I am only getting the failure when the requirements exist in the same directory as the lambda handler (main.py).The Lambda code is extremely simple and exists of two files: main.py and requirements.txt in the same directory that is passed using
source_path
.Please provide a clear and concise description of the issue you are encountering, and a reproduction of your configuration (see the
examples/*
directory for references that you can copy+paste and tailor to match your configs if you are unable to copy your exact configuration). The reproduction MUST be executable by runningterraform init && terraform apply
without any further changes.If your request is for a new feature, please use the
Feature request
template.⚠️ Note
Before you submit an issue, please perform the following first:
.terraform
directory (! ONLY if state is stored remotely, which hopefully you are following that best practice!):rm -rf .terraform/
checkterraform init
checkVersions
4.13.0
Reproduction Code [Required]
Steps to reproduce the behavior:
NO YES Created Module resource, ran plan (worked), ran apply --> got the error ## Expected behaviorCreate deployment package with pip install step and upload to s3. It works fine when requirements.txt is not present.
Actual behavior
Fails with error above when requirements.txt exists in lambda source_path directory.
Terminal Output Screenshot(s)
Output included above, but full error is here again:
Additional context