amazon-web-servicesaws-lambdaterraformserverless

Terraform lambda file archive block


I am trying to archive entire Class folder and specific lambda files to specific lambda. Class folders contains multiple class files which are common to multiple lambda as listed in lambda folder.

Here I am trying lambda1_handler.py.

Here is my folder structure

├── project
    ├── modules
        ├── lambda
            ├── lambda1_handler.py
            |-- lambda2_handler.py
            ├── library
                ├── Class1.py
                |-- Class2.py

Here is my terraform block of code for lambda1.

data "archive_file" "step_function_handler_archive" {
  type        = "zip"

  # Include the API Gateway handler file
  source {
    content = file("${path.module}/python/lambda1_handler.py")
    filename = "lambda1_handler.py"
  }

  # Include all files from the 'library' folder
  source {
    content = fileset("${path.module}/python/library", "*")
    filename = "library/"
  }

  output_path = "${path.module}/zip/lambda1_handler.zip"
}

getting error on terraform plan

│ Error: Incorrect attribute value type
│ 
│   on lambda/main.tf line 437, in data "archive_file" "step_function_handler_archive":
│  437:     content = fileset("${path.module}/python/library", "*")
│     ├────────────────
│     │ path.module is "lambda"
│ 
│ Inappropriate value for attribute "content": string required.

Solution

  • First of all I think you have those paths wrong, as I don't see any python folder in your directory tree. Then the problem is that the content property accepts a string and not a list which is what the fileset function returns. To fix this, you can use a dynamic block, e.g.:

    data "archive_file" "step_function_handler_archive" {
      type = "zip"
    
      # Include the API Gateway handler file
      source {
        content  = file("${path.module}/project/modules/lambda/lambda1_handler.py")
        filename = "lambda1_handler.py"
      }
    
      # Include all files from the 'library' folder
      dynamic "source" {
        for_each = fileset("${path.module}/project/modules/lambda/library", "*")
        content {
          content  = source.value
          filename = "library/${source.value}"
        }
      }
    
      output_path = "${path.module}/zip/lambda1_handler.zip"
    }
    

    assuming directory structure:

    .
    ├── main.tf
    ├── project
    │   └── modules
    │       └── lambda
    │           ├── lambda1_handler.py
    │           ├── lambda2_handler.py
    │           └── library
    │               ├── Class1.py
    │               └── Class2.py
    

    then:

    # run terraform
    $ terraform apply
    
    # unzip output zip to verify contents
    $ unzip zip/lambda1_handler.zip -d temp
    
    # check contents
    $ tree temp/
    temp/
    ├── lambda1_handler.py
    └── library
        ├── Class1.py
        └── Class2.py