Terraform 在创建资源之前检查资源是否存在

Mul*_*ule 17 terraform terraform-provider-gcp

Terraform 有没有办法在尝试创建资源之前检查 Google Cloud 中的资源是否存在?

我想检查作业期间我的 CircleCI CI/CD 管道中是否存在以下资源。我可以访问终端命令、bash 和 gcloud 命令。如果资源确实存在,我想使用它们。如果它们不存在,我想创建它们。我在 CircleCI 的 config.yml 中执行此逻辑,作为我可以访问终端命令和 bash 的步骤。我的目标是在需要时在 GCP 中创建必要的基础设施(资源),否则在创建后使用它们,而不会在 CI/CD 构建中出现 Terraform 错误。

如果我尝试创建已存在的资源,Terraform apply 将导致错误,提示“您已经拥有此资源”,现在我的 CI/CD 作业失败。

下面是描述我想要获取的资源的伪代码。

resource "google_artifact_registry_repository" "main" {
  # this is the repo for hosting my Docker images
  # it does not have a data source afaik because it is beta
}
Run Code Online (Sandbox Code Playgroud)

对于我的google_artifact_registry_repository资源。我的一种方法是使用数据源块执行 Terraform 应用并查看是否返回值。问题在于 google_artifact_registry_repository 没有数据源块。因此,我必须使用资源块创建此资源一次,之后的每个 CI/CD 构建都可以依赖它的存在。有没有解决方法可以读取它的存在?

resource "google_storage_bucket" "bucket" {
  # bucket containing the folder below
}

resource "google_storage_bucket_object" "content_folder" {
  # folder containing Terraform default.tfstate for my Cloud Run Service
}
Run Code Online (Sandbox Code Playgroud)

对于我的google_storage_bucketgoogle_storage_bucket_object资源。如果我使用数据源块执行 Terraform 应用来查看这些是否存在,我遇到的一个问题是当找不到资源时,Terraform 需要永远返回该状态。如果我能够在 10-15 秒之内确定资源是否存在,并且如果不存在则假设这些资源不存在,那就太好了。

data "google_storage_bucket" "bucket" {
  # bucket containing the folder below
}

output bucket {
  value = data.google_storage_bucket.bucket
}
Run Code Online (Sandbox Code Playgroud)

当资源存在时,我可以使用 Terraform 输出存储桶来获取该值。如果不存在,Terraform 需要很长时间才能返回响应。对此有什么想法吗?

Mar*_*cin 6

TF没有任何内置工具来检查是否存在预先存在的资源,因为这不是 TF 的目的。但是,您可以创建自己的自定义数据源

使用自定义数据源,您可以编写所需的任何逻辑,包括检查预先存在的资源并将该信息返回到 TF 以供将来使用。


Mul*_*ule 6

感谢 Marcin 的建议,我有一个工作示例,说明如何解决使用 Terraform 的外部数据源检查 GCP 中是否存在资源的问题检查 GCP 中是否存在资源的问题。这是一种有效的方法。我确信还有其他方法。

我有一个 CircleCI config.yml,其中有一份使用运行命令和 bash 的工作。在 bash 中,我将初始化/应用一个 Terraform 脚本来检查我的资源是否存在,如下所示。

data "external" "get_bucket" {
  program = ["bash","gcp.sh"]
  query = {
    bucket_name = var.bucket_name
  }
}

output "bucket" {
  value = data.external.get_bucket.result.name
}
Run Code Online (Sandbox Code Playgroud)

然后在我的 gcp.sh 中,我使用 gsutil 来获取我的存储桶(如果存在)。

#!/bin/bash

eval "$(jq -r '@sh "BUCKET_NAME=\(.bucket_name)"')"
bucket=$(gsutil ls gs://$BUCKET_NAME)

if [[ ${#bucket} -gt 0 ]]; then
  jq -n --arg name "" '{name:"'$BUCKET_NAME'"}'
else
  jq -n --arg name "" '{name:""}'
fi
Run Code Online (Sandbox Code Playgroud)

然后在我的 CircleCI config.yml 中,我将它们放在一起。

terraform init
terraform apply -auto-approve -var bucket_name=my-bucket
bucket=$(terraform output bucket)
Run Code Online (Sandbox Code Playgroud)

此时,我检查是否返回了存储桶名称,并根据该名称确定如何继续。