Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Adding lifecycle ignore changes to image uri #613

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 163 additions & 12 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,158 @@ locals {
s3_key = var.s3_existing_package != null ? try(var.s3_existing_package.key, null) : (var.store_on_s3 ? var.s3_prefix != null ? format("%s%s", var.s3_prefix, replace(local.archive_filename_string, "/^.*//", "")) : replace(local.archive_filename_string, "/^\\.//", "") : null)
s3_object_version = var.s3_existing_package != null ? try(var.s3_existing_package.version_id, null) : (var.store_on_s3 ? try(aws_s3_object.lambda_package[0].version_id, null) : null)

lambda_used = var.ignore_image_uri ? aws_lambda_function.image_function[0] : aws_lambda_function.this[0]

}

resource "aws_lambda_function" "this" {
count = local.create && var.create_function && !var.create_layer ? 1 : 0
count = local.create && var.create_function && !var.create_layer && !var.ignore_image_uri ? 1 : 0

function_name = var.function_name
description = var.description
role = var.create_role ? aws_iam_role.lambda[0].arn : var.lambda_role
handler = var.package_type != "Zip" ? null : var.handler
memory_size = var.memory_size
reserved_concurrent_executions = var.reserved_concurrent_executions
runtime = var.package_type != "Zip" ? null : var.runtime
layers = var.layers
timeout = var.lambda_at_edge ? min(var.timeout, 30) : var.timeout
publish = (var.lambda_at_edge || var.snap_start) ? true : var.publish
kms_key_arn = var.kms_key_arn
image_uri = var.image_uri
package_type = var.package_type
architectures = var.architectures
code_signing_config_arn = var.code_signing_config_arn
replace_security_groups_on_destroy = var.replace_security_groups_on_destroy
replacement_security_group_ids = var.replacement_security_group_ids
skip_destroy = var.skip_destroy

/* ephemeral_storage is not supported in gov-cloud region, so it should be set to `null` */
dynamic "ephemeral_storage" {
for_each = var.ephemeral_storage_size == null ? [] : [true]

content {
size = var.ephemeral_storage_size
}
}

filename = local.filename
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
s3_object_version = local.s3_object_version

dynamic "image_config" {
for_each = length(var.image_config_entry_point) > 0 || length(var.image_config_command) > 0 || var.image_config_working_directory != null ? [true] : []
content {
entry_point = var.image_config_entry_point
command = var.image_config_command
working_directory = var.image_config_working_directory
}
}

dynamic "environment" {
for_each = length(keys(var.environment_variables)) == 0 ? [] : [true]
content {
variables = var.environment_variables
}
}

dynamic "dead_letter_config" {
for_each = var.dead_letter_target_arn == null ? [] : [true]
content {
target_arn = var.dead_letter_target_arn
}
}

dynamic "tracing_config" {
for_each = var.tracing_mode == null ? [] : [true]
content {
mode = var.tracing_mode
}
}

dynamic "vpc_config" {
for_each = var.vpc_subnet_ids != null && var.vpc_security_group_ids != null ? [true] : []
content {
security_group_ids = var.vpc_security_group_ids
subnet_ids = var.vpc_subnet_ids
}
}

dynamic "file_system_config" {
for_each = var.file_system_arn != null && var.file_system_local_mount_path != null ? [true] : []
content {
local_mount_path = var.file_system_local_mount_path
arn = var.file_system_arn
}
}

dynamic "snap_start" {
for_each = var.snap_start ? [true] : []

content {
apply_on = "PublishedVersions"
}
}

dynamic "logging_config" {
# Dont create logging config on gov cloud as it is not avaible.
# See https://github.com/hashicorp/terraform-provider-aws/issues/34810
for_each = data.aws_partition.current.partition == "aws" ? [true] : []

content {
log_group = var.logging_log_group
log_format = var.logging_log_format
application_log_level = var.logging_log_format == "Text" ? null : var.logging_application_log_level
system_log_level = var.logging_log_format == "Text" ? null : var.logging_system_log_level
}
}

dynamic "timeouts" {
for_each = length(var.timeouts) > 0 ? [true] : []

content {
create = try(var.timeouts.create, null)
update = try(var.timeouts.update, null)
delete = try(var.timeouts.delete, null)
}
}

tags = merge(
{ terraform-aws-modules = "lambda" },
var.tags,
var.function_tags
)

depends_on = [
null_resource.archive,
aws_s3_object.lambda_package,

# Depending on the log group is necessary to allow Terraform to create the log group before AWS can.
# When a lambda function is invoked, AWS creates the log group automatically if it doesn't exist yet.
# Without the dependency, this can result in a race condition if the lambda function is invoked before
# Terraform can create the log group.
aws_cloudwatch_log_group.lambda,

# Before the lambda is created the execution role with all its policies should be ready
aws_iam_role_policy_attachment.additional_inline,
aws_iam_role_policy_attachment.additional_json,
aws_iam_role_policy_attachment.additional_jsons,
aws_iam_role_policy_attachment.additional_many,
aws_iam_role_policy_attachment.additional_one,
aws_iam_role_policy_attachment.async,
aws_iam_role_policy_attachment.logs,
aws_iam_role_policy_attachment.dead_letter,
aws_iam_role_policy_attachment.vpc,
aws_iam_role_policy_attachment.tracing,
]
}

resource "aws_lambda_function" "image_function" {
count = local.create && var.create_function && !var.create_layer && var.ignore_image_uri ? 1 : 0

function_name = var.function_name
description = var.description
role = var.create_role ? aws_iam_role.lambda[0].arn : var.lambda_role
Expand Down Expand Up @@ -164,6 +311,10 @@ resource "aws_lambda_function" "this" {
aws_iam_role_policy_attachment.vpc,
aws_iam_role_policy_attachment.tracing,
]
lifecycle {
ignore_changes = [image_uri]
}

}

resource "aws_lambda_layer_version" "this" {
Expand Down Expand Up @@ -235,8 +386,8 @@ resource "aws_cloudwatch_log_group" "lambda" {
resource "aws_lambda_provisioned_concurrency_config" "current_version" {
count = local.create && var.create_function && !var.create_layer && var.provisioned_concurrent_executions > -1 ? 1 : 0

function_name = aws_lambda_function.this[0].function_name
qualifier = aws_lambda_function.this[0].version
function_name = local.lambda_used
qualifier = local.lambda_used.version

provisioned_concurrent_executions = var.provisioned_concurrent_executions
}
Expand All @@ -248,8 +399,8 @@ locals {
resource "aws_lambda_function_event_invoke_config" "this" {
for_each = { for k, v in local.qualifiers : k => v if v != null && local.create && var.create_function && !var.create_layer && var.create_async_event_config }

function_name = aws_lambda_function.this[0].function_name
qualifier = each.key == "current_version" ? aws_lambda_function.this[0].version : null
function_name = local.lambda_used.function_name
qualifier = each.key == "current_version" ? local.lambda_used.version : null

maximum_event_age_in_seconds = var.maximum_event_age_in_seconds
maximum_retry_attempts = var.maximum_retry_attempts
Expand Down Expand Up @@ -277,8 +428,8 @@ resource "aws_lambda_function_event_invoke_config" "this" {
resource "aws_lambda_permission" "current_version_triggers" {
for_each = { for k, v in var.allowed_triggers : k => v if local.create && var.create_function && !var.create_layer && var.create_current_version_allowed_triggers }

function_name = aws_lambda_function.this[0].function_name
qualifier = aws_lambda_function.this[0].version
function_name = local.lambda_used.function_name
qualifier = local.lambda_used.version

statement_id_prefix = try(each.value.statement_id, each.key)
action = try(each.value.action, "lambda:InvokeFunction")
Expand All @@ -297,7 +448,7 @@ resource "aws_lambda_permission" "current_version_triggers" {
resource "aws_lambda_permission" "unqualified_alias_triggers" {
for_each = { for k, v in var.allowed_triggers : k => v if local.create && var.create_function && !var.create_layer && var.create_unqualified_alias_allowed_triggers }

function_name = aws_lambda_function.this[0].function_name
function_name = local.lambda_used.function_name

statement_id_prefix = try(each.value.statement_id, each.key)
action = try(each.value.action, "lambda:InvokeFunction")
Expand All @@ -315,7 +466,7 @@ resource "aws_lambda_permission" "unqualified_alias_triggers" {
resource "aws_lambda_event_source_mapping" "this" {
for_each = { for k, v in var.event_source_mapping : k => v if local.create && var.create_function && !var.create_layer && var.create_unqualified_alias_allowed_triggers }

function_name = aws_lambda_function.this[0].arn
function_name = local.lambda_used.arn

event_source_arn = try(each.value.event_source_arn, null)

Expand Down Expand Up @@ -395,10 +546,10 @@ resource "aws_lambda_event_source_mapping" "this" {
resource "aws_lambda_function_url" "this" {
count = local.create && var.create_function && !var.create_layer && var.create_lambda_function_url ? 1 : 0

function_name = aws_lambda_function.this[0].function_name
function_name = local.lambda_used.function_name

# Error: error creating Lambda Function URL: ValidationException
qualifier = var.create_unqualified_alias_lambda_function_url ? null : aws_lambda_function.this[0].version
qualifier = var.create_unqualified_alias_lambda_function_url ? null : local.lambda_used.version
authorization_type = var.authorization_type
invoke_mode = var.invoke_mode

Expand All @@ -425,7 +576,7 @@ resource "null_resource" "sam_metadata_aws_lambda_function" {
triggers = {
# This is a way to let SAM CLI correlates between the Lambda function resource, and this metadata
# resource
resource_name = "aws_lambda_function.this[0]"
resource_name = "local.lambda_used"
resource_type = "ZIP_LAMBDA_FUNCTION"

# The Lambda function source code.
Expand Down
24 changes: 12 additions & 12 deletions outputs.tf
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Lambda Function
output "lambda_function_arn" {
description = "The ARN of the Lambda Function"
value = try(aws_lambda_function.this[0].arn, "")
value = try(local.lambda_used.arn, "")
}

output "lambda_function_arn_static" {
Expand All @@ -11,57 +11,57 @@ output "lambda_function_arn_static" {

output "lambda_function_invoke_arn" {
description = "The Invoke ARN of the Lambda Function"
value = try(aws_lambda_function.this[0].invoke_arn, "")
value = try(local.lambda_used.invoke_arn, "")
}

output "lambda_function_name" {
description = "The name of the Lambda Function"
value = try(aws_lambda_function.this[0].function_name, "")
value = try(local.lambda_used.function_name, "")
}

output "lambda_function_qualified_arn" {
description = "The ARN identifying your Lambda Function Version"
value = try(aws_lambda_function.this[0].qualified_arn, "")
value = try(local.lambda_used.qualified_arn, "")
}

output "lambda_function_qualified_invoke_arn" {
description = "The Invoke ARN identifying your Lambda Function Version"
value = try(aws_lambda_function.this[0].qualified_invoke_arn, "")
value = try(local.lambda_used.qualified_invoke_arn, "")
}

output "lambda_function_version" {
description = "Latest published version of Lambda Function"
value = try(aws_lambda_function.this[0].version, "")
value = try(local.lambda_used.version, "")
}

output "lambda_function_last_modified" {
description = "The date Lambda Function resource was last modified"
value = try(aws_lambda_function.this[0].last_modified, "")
value = try(local.lambda_used.last_modified, "")
}

output "lambda_function_kms_key_arn" {
description = "The ARN for the KMS encryption key of Lambda Function"
value = try(aws_lambda_function.this[0].kms_key_arn, "")
value = try(local.lambda_used.kms_key_arn, "")
}

output "lambda_function_source_code_hash" {
description = "Base64-encoded representation of raw SHA-256 sum of the zip file"
value = try(aws_lambda_function.this[0].source_code_hash, "")
value = try(local.lambda_used.source_code_hash, "")
}

output "lambda_function_source_code_size" {
description = "The size in bytes of the function .zip file"
value = try(aws_lambda_function.this[0].source_code_size, "")
value = try(local.lambda_used.source_code_size, "")
}

output "lambda_function_signing_job_arn" {
description = "ARN of the signing job"
value = try(aws_lambda_function.this[0].signing_job_arn, "")
value = try(local.lambda_used.signing_job_arn, "")
}

output "lambda_function_signing_profile_version_arn" {
description = "ARN of the signing profile version"
value = try(aws_lambda_function.this[0].signing_profile_version_arn, "")
value = try(local.lambda_used.signing_profile_version_arn, "")
}

# Lambda Function URL
Expand Down
6 changes: 6 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,12 @@ variable "package_type" {
default = "Zip"
}

variable "ignore_image_uri" {
description = "Ignores changes to the image_uri"
type = bool
default = false
}

variable "image_uri" {
description = "The ECR image URI containing the function's deployment package."
type = string
Expand Down
Loading