From ca27838b076b78eaaa9dd2132e8c0155fd2c9ad3 Mon Sep 17 00:00:00 2001 From: anoshi Date: Thu, 15 Jul 2021 10:49:41 +1000 Subject: [PATCH 1/5] Ignore changes (#1) * add ignore_changes_package (source code hash) var * update CHANGELOG --- CHANGELOG.md | 2 +- README.md | 23 +++++++++++++++++++++++ main.tf | 7 +++++++ variables.tf | 6 ++++++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 757f46b3..29a58300 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - +- feat: Add `ignore_changes_package` variable to allow the lambda function resource to be managed by terraform but have the function code managed externally ## [v2.7.0] - 2021-07-08 diff --git a/README.md b/README.md index 1715f143..0f7e6d23 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,28 @@ module "lambda_function_existing_package_local" { } ``` +### Lambda Function where package deployments are maintained separately to infrastructure + +If using this method you need to be aware of the following: + +1. A 'dummy' package will need to be included with your terraform code/module. This is deployed to the function when the lambda component is initialised. +1. You will need to redeploy the real function code after the terraform apply every time the lambda function resource is recreated / force replaced; the 'dummy' package is deployed every time the lambda resource is created. + +```hcl +module "lambda_function_externally_managed_package" { + source = "terraform-aws-modules/lambda/aws" + + function_name = "my-lambda-externally-managed-package" + description = "My lambda function code is deployed separately" + handler = "index.lambda_handler" + runtime = "python3.8" + + create_package = false + local_existing_package = "../dummy_package.zip" + ignore_changes_package = true +} +``` + ### Lambda Function with existing package (prebuilt) stored in S3 bucket Note that this module does not copy prebuilt packages into S3 bucket. This module can only store packages it builds locally and in S3 bucket. @@ -664,6 +686,7 @@ No modules. | [function\_name](#input\_function\_name) | A unique name for your Lambda Function | `string` | `""` | no | | [handler](#input\_handler) | Lambda Function entrypoint in your code | `string` | `""` | no | | [hash\_extra](#input\_hash\_extra) | The string to add into hashing function. Useful when building same source path for different functions. | `string` | `""` | no | +| [ignore\_changes\_package](#input\_ignore\_changes\_package) | Set to true to ignore changes to the function's source code package/hash. Useful when infrastructure and code deployments are managed by separate pipelines | `bool` | `false` | no | | [image\_config\_command](#input\_image\_config\_command) | The CMD for the docker image | `list(string)` | `[]` | no | | [image\_config\_entry\_point](#input\_image\_config\_entry\_point) | The ENTRYPOINT for the docker image | `list(string)` | `[]` | no | | [image\_config\_working\_directory](#input\_image\_config\_working\_directory) | The working directory for the docker image | `string` | `null` | no | diff --git a/main.tf b/main.tf index bcaef9c4..eaadba4f 100644 --- a/main.tf +++ b/main.tf @@ -81,6 +81,13 @@ resource "aws_lambda_function" "this" { } } + dynamic "lifecycle" { + for_each = var.ignore_changes_package ? [true] : [] + content { + ignore_changes = [source_code_hash] + } + } + tags = var.tags # Depending on the log group is necessary to allow Terraform to create the log group before AWS can. diff --git a/variables.tf b/variables.tf index 6a683ed0..d4fc2462 100644 --- a/variables.tf +++ b/variables.tf @@ -493,6 +493,12 @@ variable "artifacts_dir" { default = "builds" } +variable "ignore_changes_package" { + description = "Set to true to ignore changes to the function's source code package/hash. Useful when infrastructure and code deployments are managed by separate pipelines" + type = bool + default = false +} + variable "local_existing_package" { description = "The absolute path to an existing zip-file to use" type = string From d156d8e156c6a38d107797891e89dc660ac2c3f4 Mon Sep 17 00:00:00 2001 From: anoshi Date: Thu, 15 Jul 2021 11:56:44 +1000 Subject: [PATCH 2/5] ignore_source_code_hash (#2) * add ignore_changes_package (source code hash) var * update CHANGELOG * ignore_source_code_hash --- CHANGELOG.md | 2 +- README.md | 6 +++--- main.tf | 9 +-------- variables.tf | 4 ++-- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29a58300..04b312d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] -- feat: Add `ignore_changes_package` variable to allow the lambda function resource to be managed by terraform but have the function code managed externally +- feat: Add `ignore_source_code_hash` variable to allow the lambda function resource to be managed by terraform but have the function code managed externally ## [v2.7.0] - 2021-07-08 diff --git a/README.md b/README.md index 0f7e6d23..b9591c68 100644 --- a/README.md +++ b/README.md @@ -122,9 +122,9 @@ module "lambda_function_externally_managed_package" { handler = "index.lambda_handler" runtime = "python3.8" - create_package = false - local_existing_package = "../dummy_package.zip" - ignore_changes_package = true + create_package = false + local_existing_package = "./lambda_functions/dummy_lambda.zip" + ignore_source_code_hash = true } ``` diff --git a/main.tf b/main.tf index eaadba4f..7dd9d339 100644 --- a/main.tf +++ b/main.tf @@ -29,7 +29,7 @@ resource "aws_lambda_function" "this" { package_type = var.package_type filename = local.filename - source_code_hash = (local.filename == null ? false : fileexists(local.filename)) && !local.was_missing ? filebase64sha256(local.filename) : null + source_code_hash = var.ignore_source_code_hash ? null : (local.filename == null ? false : fileexists(local.filename)) && !local.was_missing ? filebase64sha256(local.filename) : null s3_bucket = local.s3_bucket s3_key = local.s3_key @@ -81,13 +81,6 @@ resource "aws_lambda_function" "this" { } } - dynamic "lifecycle" { - for_each = var.ignore_changes_package ? [true] : [] - content { - ignore_changes = [source_code_hash] - } - } - tags = var.tags # Depending on the log group is necessary to allow Terraform to create the log group before AWS can. diff --git a/variables.tf b/variables.tf index d4fc2462..8d57515f 100644 --- a/variables.tf +++ b/variables.tf @@ -493,8 +493,8 @@ variable "artifacts_dir" { default = "builds" } -variable "ignore_changes_package" { - description = "Set to true to ignore changes to the function's source code package/hash. Useful when infrastructure and code deployments are managed by separate pipelines" +variable "ignore_source_code_hash" { + description = "Set to true to ignore changes to the function's source code hash. Useful when infrastructure and code deployments are managed by separate pipelines" type = bool default = false } From aa19ca05504bbbdaebc70115692164efc33b758f Mon Sep 17 00:00:00 2001 From: aag-pcameron Date: Thu, 15 Jul 2021 12:32:09 +1000 Subject: [PATCH 3/5] doco --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b9591c68..d2e0fe82 100644 --- a/README.md +++ b/README.md @@ -686,7 +686,7 @@ No modules. | [function\_name](#input\_function\_name) | A unique name for your Lambda Function | `string` | `""` | no | | [handler](#input\_handler) | Lambda Function entrypoint in your code | `string` | `""` | no | | [hash\_extra](#input\_hash\_extra) | The string to add into hashing function. Useful when building same source path for different functions. | `string` | `""` | no | -| [ignore\_changes\_package](#input\_ignore\_changes\_package) | Set to true to ignore changes to the function's source code package/hash. Useful when infrastructure and code deployments are managed by separate pipelines | `bool` | `false` | no | +| [ignore\_source\_code\_hash](#input\_ignore\_source\_code\_hash) | Set to true to ignore changes to the function's source code hash. Useful when infrastructure and code deployments are managed by separate pipelines | `bool` | `false` | no | | [image\_config\_command](#input\_image\_config\_command) | The CMD for the docker image | `list(string)` | `[]` | no | | [image\_config\_entry\_point](#input\_image\_config\_entry\_point) | The ENTRYPOINT for the docker image | `list(string)` | `[]` | no | | [image\_config\_working\_directory](#input\_image\_config\_working\_directory) | The working directory for the docker image | `string` | `null` | no | From abaee1f0b362c24e0a76053ba9a87c44df6d256e Mon Sep 17 00:00:00 2001 From: Anton Babenko Date: Fri, 20 Aug 2021 17:15:08 +0200 Subject: [PATCH 4/5] Fixed code a bit and README --- README.md | 16 ++++++++++------ examples/complete/README.md | 2 ++ examples/complete/main.tf | 38 +++++++++++++++++++++++++++++++++++++ main.tf | 2 +- 4 files changed, 51 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d2e0fe82..67c229f2 100644 --- a/README.md +++ b/README.md @@ -106,12 +106,15 @@ module "lambda_function_existing_package_local" { } ``` -### Lambda Function where package deployments are maintained separately to infrastructure +### Lambda Function or Lambda Layer with the deployable artifact maintained separately from the infrastructure -If using this method you need to be aware of the following: +If you want to manage function code and infrastructure resources (such as IAM permissions, policies, events, etc) in separate flows (e.g., different repositories, teams, CI/CD pipelines). -1. A 'dummy' package will need to be included with your terraform code/module. This is deployed to the function when the lambda component is initialised. -1. You will need to redeploy the real function code after the terraform apply every time the lambda function resource is recreated / force replaced; the 'dummy' package is deployed every time the lambda resource is created. +Disable source code tracking to turn off deployments (and rollbacks) using the module by setting `ignore_source_code_hash = true` and deploy a _dummy function_. + +When the infrastructure and the dummy function is deployed, you can use external tool to update the source code of the function (eg, using [AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/lambda/update-function-code.html)) and keep using this module via Terraform to manage the infrastructure. + +Be aware that changes in `local_existing_package` value may trigger deployment via Terraform. ```hcl module "lambda_function_externally_managed_package" { @@ -122,8 +125,9 @@ module "lambda_function_externally_managed_package" { handler = "index.lambda_handler" runtime = "python3.8" - create_package = false - local_existing_package = "./lambda_functions/dummy_lambda.zip" + create_package = false + local_existing_package = "./lambda_functions/code.zip" + ignore_source_code_hash = true } ``` diff --git a/examples/complete/README.md b/examples/complete/README.md index 5cbdce79..94d81913 100644 --- a/examples/complete/README.md +++ b/examples/complete/README.md @@ -40,8 +40,10 @@ Note that this example may create resources which cost money. Run `terraform des | [lambda\_function](#module\_lambda\_function) | ../../ | | | [lambda\_function\_existing\_package\_local](#module\_lambda\_function\_existing\_package\_local) | ../../ | | | [lambda\_function\_for\_each](#module\_lambda\_function\_for\_each) | ../../ | | +| [lambda\_function\_with\_package\_deploying\_externally](#module\_lambda\_function\_with\_package\_deploying\_externally) | ../../ | | | [lambda\_layer\_local](#module\_lambda\_layer\_local) | ../../ | | | [lambda\_layer\_s3](#module\_lambda\_layer\_s3) | ../../ | | +| [lambda\_layer\_with\_package\_deploying\_externally](#module\_lambda\_layer\_with\_package\_deploying\_externally) | ../../ | | | [lambda\_with\_mixed\_trusted\_entities](#module\_lambda\_with\_mixed\_trusted\_entities) | ../../ | | | [lambda\_with\_provisioned\_concurrency](#module\_lambda\_with\_provisioned\_concurrency) | ../../ | | | [s3\_bucket](#module\_s3\_bucket) | terraform-aws-modules/s3-bucket/aws | | diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 7a189597..348aab8c 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -167,6 +167,26 @@ module "lambda_layer_local" { source_path = "${path.module}/../fixtures/python3.8-app1" } +#################################################### +# Lambda Layer with package deploying externally +# (e.g., using separate CI/CD pipeline) +#################################################### + +module "lambda_layer_with_package_deploying_externally" { + source = "../../" + + create_layer = true + + layer_name = "${random_pet.this.id}-layer-local" + description = "My amazing lambda layer (deployed from local)" + compatible_runtimes = ["python3.8"] + + create_package = false + local_existing_package = "../fixtures/python3.8-zip/existing_package.zip" + + ignore_source_code_hash = true +} + ############################### # Lambda Layer (storing on S3) ############################### @@ -277,6 +297,24 @@ module "lambda_function_for_each" { local_existing_package = "${path.module}/../fixtures/python3.8-zip/existing_package.zip" } +#################################################### +# Lambda Function with package deploying externally +# (e.g., using separate CI/CD pipeline) +#################################################### + +module "lambda_function_with_package_deploying_externally" { + source = "../../" + + function_name = "${random_pet.this.id}-lambda-with-package-deploying-externally" + handler = "index.lambda_handler" + runtime = "python3.8" + + create_package = false + local_existing_package = "../fixtures/python3.8-zip/existing_package.zip" + + ignore_source_code_hash = true +} + ########### # Disabled ########### diff --git a/main.tf b/main.tf index 5323723a..5608b816 100644 --- a/main.tf +++ b/main.tf @@ -100,7 +100,7 @@ resource "aws_lambda_layer_version" "this" { compatible_runtimes = length(var.compatible_runtimes) > 0 ? var.compatible_runtimes : [var.runtime] filename = local.filename - source_code_hash = (local.filename == null ? false : fileexists(local.filename)) && !local.was_missing ? filebase64sha256(local.filename) : null + source_code_hash = var.ignore_source_code_hash ? null : (local.filename == null ? false : fileexists(local.filename)) && !local.was_missing ? filebase64sha256(local.filename) : null s3_bucket = local.s3_bucket s3_key = local.s3_key From 5898d8fed6aad93e9f8cbbb72a948b810d3a1496 Mon Sep 17 00:00:00 2001 From: Anton Babenko Date: Fri, 20 Aug 2021 17:17:18 +0200 Subject: [PATCH 5/5] Fixed code a bit and README --- README.md | 2 +- variables.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 67c229f2..b657f60f 100644 --- a/README.md +++ b/README.md @@ -690,7 +690,7 @@ No modules. | [function\_name](#input\_function\_name) | A unique name for your Lambda Function | `string` | `""` | no | | [handler](#input\_handler) | Lambda Function entrypoint in your code | `string` | `""` | no | | [hash\_extra](#input\_hash\_extra) | The string to add into hashing function. Useful when building same source path for different functions. | `string` | `""` | no | -| [ignore\_source\_code\_hash](#input\_ignore\_source\_code\_hash) | Set to true to ignore changes to the function's source code hash. Useful when infrastructure and code deployments are managed by separate pipelines | `bool` | `false` | no | +| [ignore\_source\_code\_hash](#input\_ignore\_source\_code\_hash) | Whether to ignore changes to the function's source code hash. Set to true if you manage infrastructure and code deployments separately. | `bool` | `false` | no | | [image\_config\_command](#input\_image\_config\_command) | The CMD for the docker image | `list(string)` | `[]` | no | | [image\_config\_entry\_point](#input\_image\_config\_entry\_point) | The ENTRYPOINT for the docker image | `list(string)` | `[]` | no | | [image\_config\_working\_directory](#input\_image\_config\_working\_directory) | The working directory for the docker image | `string` | `null` | no | diff --git a/variables.tf b/variables.tf index 8d57515f..56af85ca 100644 --- a/variables.tf +++ b/variables.tf @@ -494,7 +494,7 @@ variable "artifacts_dir" { } variable "ignore_source_code_hash" { - description = "Set to true to ignore changes to the function's source code hash. Useful when infrastructure and code deployments are managed by separate pipelines" + description = "Whether to ignore changes to the function's source code hash. Set to true if you manage infrastructure and code deployments separately." type = bool default = false }