如何在没有源码包的情况下通过Terragrunt部署AWS Lambda函数?

问题描述 投票:0回答:1

我正在尝试使用 Terragrunt 部署 AWS Lambda 函数,而不附加 zip 包。目标是使用基本配置创建功能并直接通过 Terragrunt 进行管理。

我尝试在 _common/lambdas.yml 中设置

create_package: false
,但 Terragrunt 抛出错误 Could not located source_path "null"。我尝试使用带有 local_existing_package: "./dummy.zip" 和ignore_source_code_hash: true 的虚拟包,但错误仍然存在。

这是我的配置:

第一次尝试,_common/lambdas.yml:

- function_name: test-function
  create_package: false
  description: "test-function"
  handler: "lambda_handler"
  runtime: "python3.9"
  memory_size: 128

第二次尝试,_common/lambdas.yml:

- function_name: test-function
  create_package: false
  local_existing_package: "./dummy.zip"
  ignore_source_code_hash: true
  description: "test-function"
  handler: "lambda_handler"
  runtime: "python3.9"
  memory_size: 128

terragrunt 初始化:

$ terragrunt init
10:05:37.299 INFO   Downloading Terraform configurations from git::ssh://[email protected]/terraform-aws-modules/terraform-aws-lambda.git?ref=v7.10.0 into ./.terragrunt-cache/Is4Dzy3Iy9H51bjZPDSOxArR0SA/aFgDcKCtTXEYjkO24zjTsyaNIuc
10:05:38.244 STDOUT terraform: Initializing the backend...
10:05:38.351 STDOUT terraform:
10:05:38.351 STDOUT terraform: Successfully configured the backend "s3"! Terraform will automatically
10:05:38.351 STDOUT terraform: use this backend unless the backend configuration changes.
10:05:38.448 STDOUT terraform: Initializing modules...
10:05:38.464 STDOUT terraform: - wrapper in ..
10:05:38.476 STDOUT terraform: Initializing provider plugins...
10:05:38.476 STDOUT terraform: - Finding hashicorp/aws versions matching ">= 5.32.0"...
10:05:38.500 STDOUT terraform: - Finding hashicorp/external versions matching ">= 1.0.0"...
10:05:38.508 STDOUT terraform: - Finding hashicorp/local versions matching ">= 1.0.0"...
10:05:38.517 STDOUT terraform: - Finding hashicorp/null versions matching ">= 2.0.0"...
10:05:38.550 STDOUT terraform: - Installing hashicorp/external v2.3.4...
10:05:38.733 STDOUT terraform: - Installed hashicorp/external v2.3.4 (signed by HashiCorp)
10:05:38.752 STDOUT terraform: - Installing hashicorp/local v2.5.2...
10:05:38.934 STDOUT terraform: - Installed hashicorp/local v2.5.2 (signed by HashiCorp)
10:05:38.953 STDOUT terraform: - Installing hashicorp/null v3.2.3...
10:05:39.138 STDOUT terraform: - Installed hashicorp/null v3.2.3 (signed by HashiCorp)
10:05:39.157 STDOUT terraform: - Installing hashicorp/aws v5.75.0...
10:05:44.145 STDOUT terraform: - Installed hashicorp/aws v5.75.0 (signed by HashiCorp)
10:05:44.145 STDOUT terraform: Terraform has created a lock file .terraform.lock.hcl to record the provider
10:05:44.145 STDOUT terraform: selections it made above. Include this file in your version control repository
10:05:44.145 STDOUT terraform: so that Terraform can guarantee to make the same selections by default when
10:05:44.145 STDOUT terraform: you run "terraform init" in the future.
10:05:44.146 STDOUT terraform: Terraform has been successfully initialized!
10:05:44.146 STDOUT terraform:
10:05:44.146 STDOUT terraform: You may now begin working with Terraform. Try running "terraform plan" to see
10:05:44.146 STDOUT terraform: any changes that are required for your infrastructure. All Terraform commands
10:05:44.146 STDOUT terraform: should now work.
10:05:44.146 STDOUT terraform: If you ever set or change modules or backend configuration for Terraform,
10:05:44.146 STDOUT terraform: rerun this command to reinitialize your working directory. If you forget, other
10:05:44.146 STDOUT terraform: commands will detect it and remind you to do so if necessary.

terragrunt 计划(两次尝试底部的错误消息相同):

$ terragrunt plan
10:05:53.568 STDOUT terraform: module.wrapper["function-name"].data.external.archive_prepare[0]: Reading...
10:05:54.466 STDOUT terraform: module.wrapper["function-name"].data.aws_caller_identity.current: Reading...
10:05:54.467 STDOUT terraform: module.wrapper["function-name"].data.aws_region.current: Reading...
10:05:54.467 STDOUT terraform: module.wrapper["function-name"].data.aws_iam_policy_document.assume_role[0]: Reading...
10:05:54.468 STDOUT terraform: module.wrapper["function-name"].data.aws_partition.current: Reading...
10:05:54.469 STDOUT terraform: module.wrapper["function-name"].data.aws_region.current: Read complete after 0s [id=us-east-1]
10:05:54.470 STDOUT terraform: module.wrapper["function-name"].data.aws_partition.current: Read complete after 0s [id=aws]
10:05:54.470 STDOUT terraform: module.wrapper["function-name"].data.aws_iam_policy_document.assume_role[0]: Read complete after 0s [id=2690255455]
10:05:54.470 STDOUT terraform: module.wrapper["function-name"].data.aws_caller_identity.current: Read complete after 0s [id=0***055]
10:05:54.609 STDOUT terraform: Terraform used the selected providers to generate the following execution
10:05:54.609 STDOUT terraform: plan. Resource actions are indicated with the following symbols:
10:05:54.609 STDOUT terraform:   + create
10:05:54.609 STDOUT terraform:  <= read (data resources)
10:05:54.609 STDOUT terraform: Terraform planned the following actions, but then encountered a problem:
10:05:54.609 STDOUT terraform:   # module.wrapper["function-name"].data.aws_iam_policy_document.logs[0] will be read during apply
10:05:54.609 STDOUT terraform:   # (config refers to values not yet known)
10:05:54.609 STDOUT terraform:  <= data "aws_iam_policy_document" "logs" {
10:05:54.609 STDOUT terraform:       + id            = (known after apply)
10:05:54.609 STDOUT terraform:       + json          = (known after apply)
10:05:54.609 STDOUT terraform:       + minified_json = (known after apply)
10:05:54.609 STDOUT terraform:       + statement {
10:05:54.609 STDOUT terraform:           + actions   = [
10:05:54.609 STDOUT terraform:               + "logs:CreateLogGroup",
10:05:54.609 STDOUT terraform:               + "logs:CreateLogStream",
10:05:54.609 STDOUT terraform:               + "logs:PutLogEvents",
10:05:54.609 STDOUT terraform:             ]
10:05:54.609 STDOUT terraform:           + effect    = "Allow"
10:05:54.609 STDOUT terraform:           + resources = (known after apply)
10:05:54.609 STDOUT terraform:         }
10:05:54.609 STDOUT terraform:     }
10:05:54.609 STDOUT terraform:   # module.wrapper["function-name"].aws_cloudwatch_log_group.lambda[0] will be created
10:05:54.609 STDOUT terraform:   + resource "aws_cloudwatch_log_group" "lambda" {
10:05:54.609 STDOUT terraform:       + arn               = (known after apply)
10:05:54.609 STDOUT terraform:       + id                = (known after apply)
10:05:54.609 STDOUT terraform:       + log_group_class   = (known after apply)
10:05:54.609 STDOUT terraform:       + name              = "/aws/lambda/function-name"
10:05:54.609 STDOUT terraform:       + name_prefix       = (known after apply)
10:05:54.609 STDOUT terraform:       + retention_in_days = 0
10:05:54.609 STDOUT terraform:       + skip_destroy      = false
10:05:54.609 STDOUT terraform:       + tags              = {
10:05:54.609 STDOUT terraform:          
10:05:54.609 STDOUT terraform:         }
10:05:54.609 STDOUT terraform:     }
10:05:54.609 STDOUT terraform:   # module.wrapper["function-name"].aws_iam_policy.logs[0] will be created
10:05:54.610 STDOUT terraform:   + resource "aws_iam_policy" "logs" {
10:05:54.610 STDOUT terraform:       + arn              = (known after apply)
10:05:54.610 STDOUT terraform:       + attachment_count = (known after apply)
10:05:54.610 STDOUT terraform:       + id               = (known after apply)
10:05:54.610 STDOUT terraform:       + name             = "function-name-logs"
10:05:54.610 STDOUT terraform:       + name_prefix      = (known after apply)
10:05:54.610 STDOUT terraform:       + path             = "/"
10:05:54.610 STDOUT terraform:       + policy           = (known after apply)
10:05:54.610 STDOUT terraform:       + policy_id        = (known after apply)
10:05:54.610 STDOUT terraform:       + tags             = {
10:05:54.610 STDOUT terraform:          
10:05:54.610 STDOUT terraform:         }
10:05:54.610 STDOUT terraform:     }
10:05:54.610 STDOUT terraform:   # module.wrapper["function-name"].aws_iam_role.lambda[0] will be created
10:05:54.610 STDOUT terraform:   + resource "aws_iam_role" "lambda" {
10:05:54.610 STDOUT terraform:       + arn                   = (known after apply)
10:05:54.610 STDOUT terraform:       + assume_role_policy    = jsonencode(
10:05:54.610 STDOUT terraform:             {
10:05:54.610 STDOUT terraform:               + Statement = [
10:05:54.610 STDOUT terraform:                   + {
10:05:54.610 STDOUT terraform:                       + Action    = "sts:AssumeRole"
10:05:54.610 STDOUT terraform:                       + Effect    = "Allow"
10:05:54.610 STDOUT terraform:                       + Principal = {
10:05:54.610 STDOUT terraform:                           + Service = "lambda.amazonaws.com"
10:05:54.610 STDOUT terraform:                         }
10:05:54.610 STDOUT terraform:                     },
10:05:54.610 STDOUT terraform:                 ]
10:05:54.610 STDOUT terraform:               + Version   = "2012-10-17"
10:05:54.610 STDOUT terraform:             }
10:05:54.610 STDOUT terraform:         )
10:05:54.610 STDOUT terraform:       + create_date           = (known after apply)
10:05:54.610 STDOUT terraform:       + force_detach_policies = true
10:05:54.610 STDOUT terraform:       + id                    = (known after apply)
10:05:54.610 STDOUT terraform:       + managed_policy_arns   = (known after apply)
10:05:54.610 STDOUT terraform:       + max_session_duration  = 3600
10:05:54.610 STDOUT terraform:       + name                  = "function-name"
10:05:54.610 STDOUT terraform:       + name_prefix           = (known after apply)
10:05:54.610 STDOUT terraform:       + path                  = "/"
10:05:54.610 STDOUT terraform:       + tags                  = {
10:05:54.610 STDOUT terraform:          
10:05:54.611 STDOUT terraform:         }
10:05:54.611 STDOUT terraform:       + unique_id             = (known after apply)
10:05:54.611 STDOUT terraform:     }
10:05:54.611 STDOUT terraform:   # module.wrapper["function-name"].aws_iam_role_policy_attachment.logs[0] will be created
10:05:54.611 STDOUT terraform:   + resource "aws_iam_role_policy_attachment" "logs" {
10:05:54.611 STDOUT terraform:       + id         = (known after apply)
10:05:54.611 STDOUT terraform:       + policy_arn = (known after apply)
10:05:54.611 STDOUT terraform:       + role       = "function-name"
10:05:54.611 STDOUT terraform:     }
10:05:54.611 STDOUT terraform: Plan: 4 to add, 0 to change, 0 to destroy.
10:05:54.611 STDOUT terraform:
10:05:54.611 STDERR terraform: ╷
10:05:54.611 STDERR terraform: │ Error: External Program Execution Failed
10:05:54.611 STDERR terraform: │
10:05:54.611 STDERR terraform: │   with module.wrapper["function-name"].data.external.archive_prepare[0],
10:05:54.611 STDERR terraform: │   on ../package.tf line 10, in data "external" "archive_prepare":
10:05:54.611 STDERR terraform: │   10:   program = [local.python, "${path.module}/package.py", "prepare"]
10:05:54.611 STDERR terraform: │
10:05:54.611 STDERR terraform: │ The data source received an unexpected error while attempting to execute
10:05:54.611 STDERR terraform: │ the program.
10:05:54.611 STDERR terraform: │
10:05:54.611 STDERR terraform: │ Program: /usr/bin/python3
10:05:54.611 STDERR terraform: │ Error Message: Could not locate source_path "null".  Paths are relative to
10:05:54.611 STDERR terraform: │ directory where `terraform plan` is being run
10:05:54.611 STDERR terraform: │ ("./.terragrunt-cache/Is4Dzy3Iy9H51bjZPDSOxArR0SA/aFgDcKCtTXEYjkO24zjTsyaNIuc/wrappers")
10:05:54.611 STDERR terraform: │
10:05:54.611 STDERR terraform: │ State: exit status 1
10:05:54.611 STDERR terraform: ╵
10:05:54.708 ERROR  terraform invocation failed in ./.terragrunt-cache/Is4Dzy3Iy9H51bjZPDSOxArR0SA/aFgDcKCtTXEYjkO24zjTsyaNIuc/wrappers stderr=
╷
│ Error: External Program Execution Failed
│
│   with module.wrapper["function-name
"].data.external.archive_prepare[0],
│   on ../package.tf line 10, in data "external" "archive_prepare":
│   10:   program = [local.python, "${path.module}/package.py", "prepare"]
│
│ The data source received an unexpected error while attempting to execute
│ the program.
│
│ Program: /usr/bin/python3
│ Error Message: Could not locate source_path "null".  Paths are relative to
│ directory where `terraform plan` is being run
│ ("./.terragrunt-cache/Is4Dzy3Iy9H51bjZPDSOxArR0SA/aFgDcKCtTXEYjkO24zjTsyaNIuc/wrappers")
│
│ State: exit status 1
╵

10:05:54.709 ERROR  1 error occurred:
        * [./.terragrunt-cache/Is4Dzy3Iy9H51bjZPDSOxArR0SA/aFgDcKCtTXEYjkO24zjTsyaNIuc/wrappers] exit status 1

terragrunt.hcl 用于 lambda:(我有用于提供程序等的 root terragrunt)

include "root" {
  path = find_in_parent_folders()
  expose = true
}

include "lambda" {
  path = find_in_parent_folders("modules/lambda.hcl")
  expose = true
}

locals {
  # Load the Lambda configurations from _common/lambdas.yaml
  def = merge(
    yamldecode(
      file(find_in_parent_folders("_common/lambdas.yaml", "{}")),
    )
  )

  # Set the `all_lambdas` list directly from the loaded `def` variable
  all_lambdas = "${local.def.commonlambdas}"

  # Construct the Lambda functions map with convention-based naming
  lambdas = try({
    for lambda in "${local.all_lambdas}":
      "${include.root.locals.convention-naming}-${lambda.function_name}" => merge(
        { function_name = "${include.root.locals.convention-naming}-${lambda.function_name}"
    #Source_path   = lambda.source_path


     },

        try("${lambda.options}", {})
      )
  }, {})
}

inputs = {
  # Default tags and other inputs shared across Lambdas
  defaults = {
    tags = "${include.root.locals.default_tags}"
  }

  # Lambda items to be processed
  items = "${local.lambdas}"
}

terragrunt.hcl(根):

locals {
  default_yaml_path = find_in_parent_folders("empty.yaml")
  def = merge(
    {
      enable_secrets = true
    },
    yamldecode(
      file(find_in_parent_folders("tier.yaml", local.default_yaml_path)),
    ),
    yamldecode(
      file(find_in_parent_folders("env.yaml", local.default_yaml_path)),
    ),
    yamldecode(
      file(find_in_parent_folders("regional.yaml", local.default_yaml_path)),
    ),
    yamldecode(
      file(find_in_parent_folders("_common/common.yaml", local.default_yaml_path)),
    ),
    yamldecode(
      file("${get_terragrunt_dir()}/deploy.yaml"),
    )
  )

  default_tags      = merge(local.def.default_tags, 
    { "provider_account" : local.def.provider_account, 
    "Env" : local.def.env, "Environment" : local.def.env, 
    "Rgn": local.def.rgn , "Tier" : local.def.tier })
  convention-naming = "c9-${local.def.env}-${local.def.rgn}"

}

generate "provider" {
  path = "provider.tf"
  if_exists = "overwrite_terragrunt"
  contents = <<EOF
provider "aws" {
  assume_role {
    role_arn = "arn:aws:iam::${local.def.account_id}:role/Admin"
  }
  region = "${local.def.region}"
}
EOF
}


remote_state {
  backend = "s3"
  generate = {
    path      = "backend.tf"
    if_exists = "overwrite_terragrunt"
  }
  config = {
    bucket         = "c9-${local.def.tier}-terragrunt"
    key            = "${path_relative_to_include()}/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true
    dynamodb_table = "c9-${local.def.tier}-terragrunt-lock-table"
    acl            = "bucket-owner-full-control"
    role_arn = "arn:aws:iam::${local.def.account_id}:role/Admin"
  }
}



inputs = merge(
    yamldecode(
      file(find_in_parent_folders("tier.yaml", local.default_yaml_path)),
    ),
    yamldecode(
      file(find_in_parent_folders("env.yaml", local.default_yaml_path)),
    ),
    yamldecode(
      file(find_in_parent_folders("regional.yaml", local.default_yaml_path)),
    ),
    yamldecode(
      file(find_in_parent_folders("_common/common.yaml", local.default_yaml_path)),
    ),
    yamldecode(
      file("${get_terragrunt_dir()}/deploy.yaml"),
    )

文件树/结构:

repo
├── terragrunt.hcl
├── _common
│   └── lambdas.yaml
└── dev
    └── dev4
        └── use1
            └── lambda
                ├── dummy.zip
                ├── deploy.yaml
                └── terragrunt.hcl
            

deploy.yaml 为空,所有函数都将位于 _common/lambdas.yaml 中。此设置是公司创建/迁移资源的方式,因此我无法更改它。

amazon-web-services lambda terraform terragrunt
1个回答
0
投票

我相信您遇到这个问题是因为 archive_prepare 步骤,尝试找到用于打包的 source_path,即使您试图绕过它。 因此 AWS Lambda 模块 common/lambdas.yaml 中的 archive_prepare 进程需要 source_path 变量。 因此,您要么提供一个 source_path,Terraform 会尝试将其打包到一个 zip 文件中,要么直接提供一个文件名来指向您的 dummy.zip:

- function_name: test-function
  create_package: false
  filename: "./dummy.zip"  # Point to the dummy package
  ignore_source_code_hash: true
  description: "test-function"
  handler: "lambda_handler"
  runtime: "python3.9"
  memory_size: 128
© www.soinside.com 2019 - 2024. All rights reserved.