aws / aws-sam-cli

CLI tool to build, test, debug, and deploy Serverless applications using AWS SAM

Home Page:https://aws.amazon.com/serverless/sam/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Native support for Terraform in SAM CLI (now in Beta)

praneetap opened this issue · comments

Terraform Support

Recently we added native support for CDK applications in the SAM CLI - you can see our launch announcement blog post and download the beta version of the CLI.

We would like to collect the community’s feedback on whether we should add native support for Terraform in the SAM CLI. Terraform users would be able to use the SAM CLI’s build, package, local invoke, and start-api commands. The build and package commands make it easy to create deployment packages or OCI images that are ready to be used in AWS Lambda. The local invoke and start-api commands makes it easy to emulate AWS Lambda and API Gateway in local Docker container for testing purposes.

With this change, the SAM CLI would parse HCL definitions to understand functions and APIs that can be locally tested and built. The SAM CLI would not write HCL, translate to, or force the use of CloudFormation. Deployments should still be performed using the Terraform toolkit.

What feedback are we looking for?

  1. Is this something the community is interested in? **Vote with 👍🏽 **.
  2. The sam build, package, and local invoke commands rely on the CodeUri property of a function resource pointing to a local path where the source code for the Lambda function is stored. The SAM CLI automatically pulls dependencies, compiles if necessary, and prepares a deployment package for AWS Lambda. The package command today produces an output template that contains the S3 URL for the deployment package the SAM CLI prepared. How would you like this work with Terraform?

The sam build, package, and local invoke commands rely on the CodeUri property of a function resource pointing to a local path where the source code for the Lambda function is stored. The SAM CLI automatically pulls dependencies, compiles if necessary, and prepares a deployment package for AWS Lambda. The package command today produces an output template that contains the S3 URL for the deployment package the SAM CLI prepared. How would you like this work with Terraform?

The "usual" way of doing Lambdas with Terraform is to use a module that abstracts the Lambda build and IaC boilerplate. A great module is serverless.tf's terraform-aws-lambda module. I'd love to see sam-beta-terraform integrate with that, maybe as an alternative to the current package.py script used to do builds? Would that make sense @antonbabenko?

I am imagining a repo like this:

.
├── template.yaml # the SAM config file for local work + Terraform integration
├── entrypoint.py 
├── functions     # the Lambda functions code
│   ├── one
│   │  ├── one.py
│   │  └── test_one.py
│   └── two
│      ├── two.py
│      └── test_two.py
├── deploy        # the Terraform IaC code
│   ├── dev
│   │  ├── lambda.tf
│   │  ├── dynamodb.tf
│   │  ├── alb.tf
│   │  └── main.tf
│   └── prod
│      ├── lambda.tf
│      ├── dynamodb.tf
│      ├── alb.tf
│      └── main.tf
├── requirements.txt
├── README.md
└── LICENSE

As a developer, I would clone the above repo, run sam local invoke and sam local start-api and I could instantly start working on the Lambda code! I would expect sam local start-api to support API Gateways defined both directly and through Terraform modules.

In the CI/CD pipeline, terraform plan and terraform apply would call out to sam build (and maybe also to sam deploy to upload the package to S3) and use the resulting package.

@Vlaaaaaaad I like the idea of bringing an alternative approach to the package.py with the main goal to make the module independent from Python and cross-platform right away.

(When we were making the terraform-aws-lambda module module, sam build was far from feature-rich. Since there is support for running Lambda functions from a container image, I recommend using that instead of relying on package.py which is not perfect. See container-image example.)

Terraform has its own resource lifecycle management which is carefully implemented as a part of the terraform-aws-lambda module. For example, rebuild the package and redeploy it only if something in dependencies changed. This does not sound like an easy task for me to even describe how Terraform & SAM should share the lifecycle management since resources can be cross-linked between SAM template and Terraform code.

As a developer, I like to have a tool that does comprehensive infrastructure management and serverless application deployments. terraform apply is it.

Yes, there is more to be done to improve the developer experience but it is not related to SAM CLI or this issue.

Terraform has its own resource lifecycle management which is carefully implemented as a part of the terraform-aws-lambda module. For example, rebuild the package and redeploy it only if something in dependencies changed. This does not sound like an easy task for me to even describe how Terraform & SAM should share the lifecycle management since resources can be cross-linked between SAM template and Terraform code.

Good point!
I was imagining sam build generating some kind of hashed artifact that can safely be used by Terraform. Having unnecessary deploys because of packaging would definitely ruin the dev experience. @praneetap any chance this would be an option?

@Vlaaaaaaad @antonbabenko Thank you for the feedback - this is helpful. To help us prioritize and make the integration decision, do you know how many Lambda users rely on the terraform-aws-lambda module? Could we get their +1s here if you are connected to the community?

@praneetap Let me share some statistics for the terraform-aws-lambda module.

  1. Terraform Registry page says Total provisions: 11.5M on November 2022 (April 2022: 4.9M). This is more than all other Lambda modules published in the Registry combined.
  2. GitHub insights for the repo says: 457,925 Clones, 86,982 Unique cloners during the last 14 days.
  3. Some users use private forks of the module or don't use Terraform Registry (e.g., using terragrunt).

I will share this issue with the community if anyone wants to upvote it.

The only issue is that my projects use GraphQL, so sam local start-api isn't as helpful since i'm using AppSync and in some cases the serverless framework which hosts its own Apollo server.

@debragail thanks for your input! We just published our open roadmap that proposes to address your issue in a couple ways - Cloud based development or building emulator plugins. Take a look and upvote the one that would work well for you.

Hello All,

I am trying to collect some data to know if the following pattern (defining multiple lambda functions and lambda layers using the count property, and t set the function.layers property to the corresponding layer using count.index) is commonly used pattern or not :

resource "aws_lambda_layer_version" "layer" {
  count = 2
  filename   = var.layers_source_code[count.index]
  ....
}

resource "aws_lambda_function" "get_country_languages" {
    count = 2
    filename = var.functions_source_code[count.index]
    ...
    layers = [aws_lambda_layer_version.layer[count.index].arn]
}

Also, if the following pattern (use conditional expression to set the Lambda function layers property) is commonly used

resource "aws_lambda_function" "get_country_languages" {
    count = 2
    filename = var.functions_source_code[count.index]
    ...
    layers = var.env == "prod" ? [aws_lambda_layer_version.prod_layer.arn] : [aws_lambda_layer_version.beta_layer.arn]
}

I appreciate if you can share with us form your experience with using terraform if you used any of these patterns in any of your terraform projects.

@moelasmar Here are my 5 cents into this.

  1. Using count is less flexible for cases where an order is not critical, so users should prefer to use for_each instead.
  2. Using conditional expressions to set Lambda layers property is possible but I don't think many users would do it this way. An alternative solution would be to use try() like this - layers = try([aws_lambda_layer_version.prod_layer.arn], [aws_lambda_layer_version.beta_layer.arn], [])

"commonly used pattern" is a rather tricky thing to ask because if it is valid syntax, there are users who write it like this, and any tool/solution should support it.

Hello!
SUPER excited to announce that our first step towards the full support - the ability to locally test and debug Lambda functions with SAM CLI, is now available in Beta. For the best experience, use it with terraform-aws-modules maintained by @antonbabenko , but you can also use it with custom modules as described in this blogpost. More details in the what's new post here.

How can you help? As you can see, this is a preview of just the Lambda function testing, and we want to build on this based on your feedback and feature requests. You can give us feedback by-

  1. Creating an issue to track a request
  2. Connect with us on AWS developer Slack #samdev channel

Thanks in advance!

Is there an example somewhere of using this support with terraform-aws-modules project? I checked the docs there, and the examples directory, and also the aws-samples repo, but didn't see anything...

I'm seeing "Error: Import error - HookFunctionality module "samcli.hook_packages.terraform.main"" when attempting to build against both the example function in the blog post or my own functions.

AWS CLI version: aws-cli/2.9.0 Python/3.9.11 Linux/5.15.74.2-microsoft-standard-WSL2 exe/x86_64.ubuntu.22 prompt/off
SAM CLI, version 1.65.0
Terraform v1.3.5

SAM CLI output:
sam build --hook-name terraform --beta-features --debug
2022-11-18 14:37:52,784 | Config file location: /tmp/aws-sam-terraform-examples/zip_based_lambda_functions/api-lambda-dynamodb-example/samconfig.toml
2022-11-18 14:37:52,784 | Config file '/tmp/aws-sam-terraform-examples/zip_based_lambda_functions/api-lambda-dynamodb-example/samconfig.toml' does not exist
2022-11-18 14:37:52,784 | Looking for internal hook package
2022-11-18 14:37:52,784 | Loaded internal hook package "terraform"
2022-11-18 14:37:52,786 | --beta-features flag is enabled, enabling experimental flag.
2022-11-18 14:37:52,786 |
Experimental features are enabled for this session.
Visit the docs page to learn more about the AWS Beta terms https://aws.amazon.com/service-terms/.

2022-11-18 14:37:52,786 | Running Prepare Hook to prepare the current application
2022-11-18 14:37:52,786 | Executing prepare hook of hook "terraform"
Error: Import error - HookFunctionality module "samcli.hook_packages.terraform.main"

@tam116 .. could you please let us know how did you install SAM CLI, and what is your OS?

I am having the same issue of:

Running Prepare Hook to prepare the current application
Executing prepare hook of hook "terraform"
Error: Import error - HookFunctionality module "samcli.hook_packages.terraform.main"

I am running in a container from Ubuntu 22.04 and installed sam cli via

# INSTALL | SAM CLI
RUN wget -O /tmp/samcli.zip https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip
RUN unzip /tmp/samcli.zip -d /tmp/sam-installation
RUN /tmp/sam-installation/install
RUN rm /tmp/samcli.zip && rm -rf /tmp/sam-installation
➜  api-lambda-dynamodb-example git:(main) ✗ sam --version
SAM CLI, version 1.65.0

@tam116 .. could you please let us know how did you install SAM CLI, and what is your OS?

OS is Ubuntu 22.04 running under WSL2

SAM install was done using the Linux instructions here: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html#install-sam-cli-instructions

thanks @philipws, and @tam116 for raising this issue. I can reproduce it, and we are working on a fix for it.

@philipws, and @tam116 I created this issue #4432 to track this problem.

@tam116, @philipws .. This issue is fixed in this sam nightly release. As a workaround for now, please follow these instructions to install the sam nightly version. We will update this issue once we release this fix.

@moelasmar The nightly build is working for me

I've made a couple of feature requests, #4439 and #4440

Thanks @tam116 for raising these requests. I replied to them and suggested some workarounds that you can try for now till we prioritized them and add a native SAM CLI support for them.

Just an update to this thread, for people who are working on Linux, SAM CLI v1.66.0 should fix the problem of not able to run terraform support feature. Please give it a try and let us know your feedback about the feature. Thanks.

Current support for sam local invoke and sam local start-lambda is proving very helpful for debugging individual functions. However support for sam local start-api would make local testing of a whole application way simpler. Any updates on how far in the roadmap is support for start-api?

I prefer to use terraform-aws-lambda module module to provision my lambda and related infra ressouces, and only use SAM to deploy the application. This seems impossible with the current way sam works because it needs to use my previously created lambda but instead wants to create a new one.

Thanks for the feedback. I created a discussion thread to better capture the beta feedbacks at the mean time. Please feel free to discussion in the new discussion thread :) Happy testing!

Closing as this was moved to Discussion (see above comment).

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

We release the Terraform support in sam local start-api for V1 API Gateway resources in release V1.90.0. Now you can test your V1 API Gateway services that integrate to lambda functions locally. Please let us know if you have any feedback. Please refer to this Docs to get more info regarding SAM CLI and Terraform integrations.

Terraform support in SAM CLI tool is GA now (announcement) in release 1.97.0.
Please refer to this blogpost to know what is supported in the new SAM CLI release, and also refer to this docs to get more info regarding the SAM CLI and Terraform integrations.