terraform-aws-modules / terraform-aws-lambda

Terraform module, which takes care of a lot of AWS Lambda/serverless tasks (build dependencies, packages, updates, deployments) in countless combinations 🇺🇦
https://registry.terraform.io/modules/terraform-aws-modules/lambda/aws
Apache License 2.0
909 stars 682 forks source link

psutil when installed from a requirements.txt fails to import properly #450

Closed myz540 closed 1 year ago

myz540 commented 1 year ago

Description

When trying to create a layer that has psutil. The package builds just fine and passes the eye test, but when deployed and included as a dependent layer, the subsequent import statement in the lambda function results in an ImportError

Versions

Reproduction Code [Required]

To reproduce the error, you'll need 3 files, the lambda.tf file, the requirements.txt file, and a lambda_function.py file. Put the lambda_function.py into a folder called lambda to prevent packaging all the terraform modules

./terraform file

module "lambda_function" {
  source = "terraform-aws-modules/lambda/aws"

  function_name            = "test_psutil_lambda"
  handler                  = "lambda_function.lambda_handler"
  runtime                  = "python3.9"
  publish                  = true
  compatible_architectures = ["x86_64"]

  create_role = true
  build_in_docker = true
  create_package  = true
  create_function = true

  source_path = "./lambda"

  layers = [
    module.lambda_layer.lambda_layer_arn,
    "arn:aws:lambda:us-west-2:336392948345:layer:AWSDataWrangler-Python39:8"
  ]
}

module "lambda_layer" {
  source = "terraform-aws-modules/lambda/aws"

  create_layer = true

  layer_name               = "test_layer"
  compatible_runtimes      = ["python3.9"]
  compatible_architectures = ["x86_64"]

  build_in_docker = true
  runtime         = "python3.9"
  source_path = [
  {
    pip_requirements = "./requirements.txt"
    prefix_in_zip = "python"
  }
  ]
}

./requirements.txt

psutil
pyyaml

./lambda/lambda_function.py

import os
import yaml  # This is in the layer
from pprint import pprint

def lambda_handler(event, context):
    """
    This method is invoked by AWS
    """
    pprint(os.listdir("/opt/python/psutil"))
    import psutil # this fails

Now, you can just invoke the lambda function to observe the ImportError

Expected Behavior

I would expect the module to load and not hit an ImportError

Actual behavior

Test Event Name
test

Response
{
  "errorMessage": "/opt/python/psutil/_psutil_linux.abi3.so: cannot open shared object file: No such file or directory",
  "errorType": "ImportError",
  "requestId": "00427390-4903-48eb-a292-bafb9e7e26d9",
  "stackTrace": [
    "  File \"/var/task/lambda_function.py\", line 14, in lambda_handler\n    import psutil\n",
    "  File \"/opt/python/psutil/__init__.py\", line 102, in <module>\n    from . import _pslinux as _psplatform\n",
    "  File \"/opt/python/psutil/_pslinux.py\", line 26, in <module>\n    from . import _psutil_linux as cext\n"
  ]
}

Function Logs
START RequestId: 00427390-4903-48eb-a292-bafb9e7e26d9 Version: $LATEST
['__init__.py',
'_common.py',
'_compat.py',
'_psaix.py',
'_psbsd.py',
'_pslinux.py',
'_psosx.py',
'_psposix.py',
'_pssunos.py',
'_psutil_linux.abi3.so',
'_psutil_posix.abi3.so',
'_pswindows.py',
'tests']
[ERROR] ImportError: /opt/python/psutil/_psutil_linux.abi3.so: cannot open shared object file: No such file or directory
Traceback (most recent call last):
  File "/var/task/lambda_function.py", line 14, in lambda_handler
    import psutil
  File "/opt/python/psutil/__init__.py", line 102, in <module>
    from . import _pslinux as _psplatform
  File "/opt/python/psutil/_pslinux.py", line 26, in <module>
    from . import _psutil_linux as cextEND RequestId: 00427390-4903-48eb-a292-bafb9e7e26d9

Terminal Output Screenshot(s)

Lambda log above

Additional context

This is an issue we are just encountering as we are trying to re-factor our lambda code to use this module. Overall, we like the module a lot but this has been a roadblock for us. It's unclear why our current build + packaging has a working psutil import but this configuration does not. Also, we had to add prefix_in_zip = "python" to get the source paths to import anything at all. In our example, we import yaml to show that the requirements were installed.

Of note, we are able to see the _psutil_linux.abi3.so as listed in the location where it is looking but unclear why it isn't being imported

myz540 commented 1 year ago

Looking into this more closely, I've determined that I can get this to work by specifying the docker_image as the lambda runtime image instead of the default build image. Setting docker_image = public.ecr.aws/lambda/python:3.9-x86_64 fixes it, but this is still not ideal since it suggests ABI compatibility issues between the lambda runtime and the supported SAM build containers (which are used here)

github-actions[bot] commented 1 year ago

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

github-actions[bot] commented 1 year ago

This issue was automatically closed because of stale in 10 days

myz540 commented 1 year ago

Hello, why was this issue not addressed and closed? This is still not addressed and the latest python 3.9 runtime update on 6/12/23 has broken it again!

github-actions[bot] commented 1 year ago

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.