Terraform - Error when Creating Lambda Versions - amazon-web-services

I'm trying to do an AWS-Terraform-GitHub pipeline for a serverless app. In terraform i define a lambda function and on push i want to update the lambda function code and create a new lambda function version (to be used with an alias at a later date).
This is my code
data "archive_file" "zip" {
type = "zip"
source_file = "${path.module}/lambda/hello.js"
output_path = "${path.module}/lambda/hello.zip"
}
resource "aws_lambda_function" "hello_terraform" {
filename = data.archive_file.zip.output_path
source_code_hash = filebase64sha256(data.archive_file.zip.output_path)
function_name = var.project_name
role = aws_iam_role.lambda_role.arn
handler = "hello.handler"
runtime = "nodejs12.x"
timeout = 10
publish = true
}
data "aws_iam_policy_document" "lambda_assume_role_policy" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["lambda.amazonaws.com"]
}
}
}
resource "aws_iam_role" "lambda_role" {
name = "${var.project_name}-lambda-role"
assume_role_policy = data.aws_iam_policy_document.lambda_assume_role_policy.json
}
When i do the initial push , or a a change that does not involve the code in lambda function everything works. However when i do a code modification i get this error on github workflow (on terraform apply)
│ Error: Error publishing Lambda Function (lambda-terraform-github-actions) version: ResourceConflictException: The operation cannot be performed at this time. An update is in progress for resource: arn:aws:lambda:us-east-1:961736190498:function:lambda-terraform-github-actions
│ {
│ RespMetadata: {
│ StatusCode: 409,
│ RequestID: "d8c86252-a471-46be-9662-751fc935083c"
│ },
│ Message_: "The operation cannot be performed at this time. An update is in progress for resource: arn:aws:lambda:us-east-1:961736190498:function:lambda-terraform-github-actions",
│ Type: "User"
│ }
│
│ with aws_lambda_function.hello_terraform,
│ on lambda.tf line 9, in resource "aws_lambda_function" "hello_terraform":
│ 9: resource "aws_lambda_function" "hello_terraform" {
│
╵
Operation failed: failed running terraform apply (exit 1)
I try adding depends_on but i still have the same problem .
I also try the same thing on a local environment , doing terraform apply on the same code without the pipeline but the same thing happens.
If i remove the "publish" the terraform apply works, the function gets updates but of course there is no new function version.

Related

Is it not possible to change an aws api gateway path and source_arn?

While working on a project managed by terraform, I have tried changing the path to an endpoint, and it gave me the following error while deploying
│ Error: Provider produced inconsistent final plan
│
│ When expanding the plan for
│ aws_lambda_permission.lambdaApiGetStockPermission to include new values
│ learned so far during apply, provider "registry.terraform.io/hashicorp/aws"
│ produced an invalid new value for .source_arn: was
│ cty.StringVal("arn:aws:execute-api:eu-west-3:<account-id>:<api-id>/*/POST/stock"),
│ but now
│ cty.StringVal("arn:aws:execute-api:eu-west-3:<account-id>:<api-id>/*/POST/stockDispoOfArticle").
│
│ This is a bug in the provider, which should be reported in the provider's
│ own issue tracker.
Subsequent deployment attemps provided the following error messages:
│ Error: Error creating API Gateway Deployment: BadRequestException: No integration defined for method
│
│ with aws_api_gateway_deployment.ApiDeployment,
│ on api.tf line 50, in resource "aws_api_gateway_deployment" "ApiDeployment":
│ 50: resource "aws_api_gateway_deployment" "ApiDeployment" {
None of those errors are seen when I launch terraform plan locally, and those errors are seen in out gitlab-ci executions
This is how we define the following resources
resource "aws_api_gateway_deployment" "ApiDeployment" {
depends_on = [
...
aws_api_gateway_integration.lambdaApiGetStock,
...
]
rest_api_id = aws_api_gateway_rest_api.Api.id
stage_name = "latest"
variables = {
deployed_at = timestamp()
}
lifecycle {
create_before_destroy = true
}
}
resource "aws_api_gateway_integration" "lambdaApiGetStock" {
rest_api_id = aws_api_gateway_rest_api.Api.id
resource_id = local.lambdaApiGetStockRouteParent
http_method = aws_api_gateway_method.lambdaApiGetStock.http_method
type = "AWS_PROXY"
uri = aws_lambda_function.lambdaApiGetStock.invoke_arn
integration_http_method = "POST"
}
resource "aws_api_gateway_method" "lambdaApiGetStock" {
rest_api_id = aws_api_gateway_rest_api.Api.id
resource_id = local.lambdaApiGetStockRouteParent
http_method = local.lambdaApiGetStockMethod
api_key_required = false
authorization = "CUSTOM"
authorizer_id = aws_api_gateway_authorizer.ApiAuthorizer.id
}
resource "aws_lambda_permission" "lambdaApiGetStockPermission" {
statement_id = "AllowExecutionFromAPIGateway"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.lambdaApiGetStock.arn
principal = "apigateway.amazonaws.com"
source_arn = "arn:aws:execute-api:${var.region}:${var.aws_account_id}:${aws_api_gateway_rest_api.Api.id}/*/${aws_api_gateway_method.lambdaApiGetStock.http_method}${local.lambdaApiGetStockRoutePath}"
}
locals {
...
lambdaApiGetStockMethod = "POST"
lambdaApiGetStockRouteParent = aws_api_gateway_resource.ApiResourceGetStock.id
lambdaApiGetStockRoutePath = aws_api_gateway_resource.ApiResourceGetStock.path
...
}
resource "aws_api_gateway_resource" "ApiResourceGetStock" {
rest_api_id = aws_api_gateway_rest_api.Api.id
parent_id = aws_api_gateway_rest_api.Api.root_resource_id
path_part = "stockDispoOfArticle"
}
I do not have permissions to see anything in the API Gateway section of the AWS console
The endpoint that I have tried to change is still available at its old path
Below is the terraform version being used:
provider "registry.terraform.io/hashicorp/aws" {
version = "4.23.0"
hashes = [
"h1:JDJLmKK61GLw8gHQtCzmvlwPNZIu46/M5uBg/TDlBa0=",
"zh:17adbedc9a80afc571a8de7b9bfccbe2359e2b3ce1fffd02b456d92248ec9294",
"zh:23d8956b031d78466de82a3d2bbe8c76cc58482c931af311580b8eaef4e6a38f",
"zh:343fe19e9a9f3021e26f4af68ff7f4828582070f986b6e5e5b23d89df5514643",
"zh:6b8ff83d884b161939b90a18a4da43dd464c4b984f54b5f537b2870ce6bd94bc",
"zh:7777d614d5e9d589ad5508eecf4c6d8f47d50fcbaf5d40fa7921064240a6b440",
"zh:82f4578861a6fd0cde9a04a1926920bd72d993d524e5b34d7738d4eff3634c44",
"zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
"zh:a08fefc153bbe0586389e814979cf7185c50fcddbb2082725991ed02742e7d1e",
"zh:ae789c0e7cb777d98934387f8888090ccb2d8973ef10e5ece541e8b624e1fb00",
"zh:b4608aab78b4dbb32c629595797107fc5a84d1b8f0682f183793d13837f0ecf0",
"zh:ed2c791c2354764b565f9ba4be7fc845c619c1a32cefadd3154a5665b312ab00",
"zh:f94ac0072a8545eebabf417bc0acbdc77c31c006ad8760834ee8ee5cdb64e743",
]
}
Was the fact of changing the path (and thus the source_arn) of the endpoint something that cannot be done? If not, what could be used as a workaround to make the changes available?
After having someone who had the permissions to view the API Gateway interface on the AWS console check what is present, an old method using GET for the lambdaApiGetStock was still present in the console, and could not be deleted by terraform somehow
They had to delete the old unused method, and afterwards, subsequent deployments went smoothly

Error updating ACL for bucket: Invalid argument

I am trying to create a container registry and add the service account with the OWNER role by changing the google_storage_bucket_acl.
According to the docs, the name of that bucket can be accessed via google_container_registry.<name>.id.
resource "google_container_registry" "registry" {
project = var.project_id
location = "EU"
}
resource "google_storage_bucket_acl" "image_store_acl" {
depends_on = [google_container_registry.registry]
bucket = google_container_registry.registry.id
role_entity = [
"OWNER:${local.terraform_service_account}",
]
}
$terraform plan
..
Terraform will perform the following actions:
# google_storage_bucket_acl.image_store_acl will be created
+ resource "google_storage_bucket_acl" "image_store_acl" {
+ bucket = "eu.artifacts.dev-00-ebcd.appspot.com"
+ id = (known after apply)
+ role_entity = [
+ "OWNER:terraform-service-account#dev-00-ebcd.iam.gserviceaccount.com",
]
}
Plan: 1 to add, 0 to change, 0 to destroy.
However, if I run terraform apply, the following error is what I get:
google_storage_bucket_acl.image_store_acl: Creating...
╷
│ Error: Error updating ACL for bucket eu.artifacts.dev-00-ebcd.appspot.com: googleapi: Error 400: Invalid argument., invalid
│
│ with google_storage_bucket_acl.image_store_acl,
│ on docker.tf line 6, in resource "google_storage_bucket_acl" "image_store_acl":
│ 6: resource "google_storage_bucket_acl" "image_store_acl" {
│
╵

How to create S3 bucket and Lambda in Terraform when they are codependent on each other?

I am creating a Lambda function that has it's handler code stored in an S3 bucket. I need to create these resources and I am using Terraform.
It appears the S3 bucket is dependent on the Lambda's ARN output so that I can set the correct Principal config for the bucket.
The Lambda is also dependent on the S3 bucket existing so I can configure the bucket which stores the handler code.
I have 2 modules creating the required resources
# S3 Bucket module
resource "aws_s3_bucket" "s3-lambda" {
bucket = var.bucket_name
acl = "private"
policy = data.aws_iam_policy_document.s3_lambda_permissions.json
tags = {
Name = var.tag_name
Environment = var.env_name
}
}
# Lambda module
resource "aws_lambda_function" "redirect_lambda" {
s3_bucket = var.bucket_name
s3_key = var.key
handler = var.handler
runtime = var.runtime
role = aws_iam_role.redirect_lambda.arn
function_name = "redirect_lambda-${var.env_name}"
publish = true
}
I am then calling these modules in my main.tf
module "qr_redirect_lambda" {
source = "./modules/qr-redirect"
env_name = var.env_name
bucket_name = var.qr_redirect_lambda_bucket_name
key = var.lambda_key
runtime = var.lambda_runtime_16
handler = var.lambda_handler
tag_name = "tag name
}
How can I create these 2 resources that are codependent on each other?
Error output:
Error: error creating Lambda Function (1): InvalidParameterValueException: Error occurred while GetObject. S3 Error Code: NoSuchBucket. S3 Error Message: The specified bucket does not exist
│ {
│ RespMetadata: {
│ StatusCode: 400,
│ RequestID: "xxx-xxx"
│ },
│ Message_: "Error occurred while GetObject. S3 Error Code: NoSuchBucket. S3 Error Message: The specified bucket does not exist",
│ Type: "User"
│ }
│
│ with module.qr_redirect_lambda.aws_lambda_function.qr_redirect_lambda,
│ on modules/qr-lambda/main.tf line 1, in resource "aws_lambda_function" "qr_redirect_lambda":
│ 1: resource "aws_lambda_function" "qr_redirect_lambda" {
I think you can do this it in three stages, instead of two:
Create bucket without bucket policy
Create lambda. You can use depends_on to create the lambda only after the bucket.
Use aws_s3_bucket_policy to create the bucket policy.

ValidationError: The specified value for roleName is invalid

I've successfully applied and deployed this script a week ago. I made 0 changes since then, to the script or to other factors used within this. Running it this morning throws this -
Terraform v1.0.8
on linux_amd64
Configuring remote state backend...
Initializing Terraform configuration...
aws_iam_role.iam_for_lambda: Refreshing state... [id=iam_for_lambda]
aws_lambda_function.lambda: Refreshing state... [id=MissingPostedTransactions]
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_iam_role_policy_attachment.tf_vpc_execution_policy will be created
+ resource "aws_iam_role_policy_attachment" "tf_vpc_execution_policy" {
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
+ role = "arn:aws:iam::<arn no>:role/iam_for_lambda"
}
Then I type "yes" to apply the supposed "change", and I get this -
aws_iam_role_policy_attachment.tf_vpc_execution_policy: Creating...
╷
│ Error: Error attaching policy arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole to IAM Role arn:aws:iam::<arn no>:role/iam_for_lambda: ValidationError: The specified value for roleName is invalid. It must contain only alphanumeric characters and/or the following: +=,.#_-
│ status code: 400, request id: 8d354476-df67-4c2d-b3b8-c7aa7efce060
│
│ with aws_iam_role_policy_attachment.tf_vpc_execution_policy,
│ on main.tf line 55, in resource "aws_iam_role_policy_attachment" "tf_vpc_execution_policy":
│ 55: resource "aws_iam_role_policy_attachment" "tf_vpc_execution_policy" {
What am I missing here?
Everything is ok in your resources except you should specify role_name and not role_arn. Please refer to documentation from Terraform for more info:
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
+ role = "<ROLE_NAME>"
}

terraform create pub/sub on gcp gives error

I have the following terraform file
provider "google" {
project = "prj1-user"
region = "APAC"
zone = "australia-southeast1-a"
}
resource "google_pubsub_topic" "prj1-messages" {
name = "prj1Messages"
labels = {
foo = "bar"
}
}
however when I try to provision this through terraform apply I get the following error
│ Error: Error creating Topic: Put "https://pubsub.googleapis.com/v1/projects/prj1-user/topics/prj1Messages?alt=json": oauth2/google: invalid token JSON from metadata: EOF
│
│ with google_pubsub_topic.brwmessages,
│ on main.tf line 7, in resource "google_pubsub_topic" "prj1Messages":
│ 7: resource "google_pubsub_topic" "prj1Messages" {
The version I'm using is
Terraform v1.0.0
on linux_amd64
+ provider registry.terraform.io/hashicorp/google v3.71.0