使用Terraform在GCP Bucket创建层级文件夹报错,求单资源实现方案
在GCP Bucket中通过Terraform创建层级文件夹结构的问题
我尝试通过Terraform在启用分层命名空间的GCP Bucket中创建层级文件夹结构,但遇到了父文件夹未创建就尝试创建子文件夹的错误。
现有代码
variable.tf
variable "folders" { type = list(string) default = ["folder1", "folder2", "folder3", "folder1/subfolder1"] } variable "create_storage_folder" { description = "Option to create folders" type = bool default = true }
main.tf
resource "google_storage_bucket" "bucket" { name = "bucket-123" location = "europe-west2" uniform_bucket_level_access = true force_destroy = true storage_class = "COLDLINE" hierarchical_namespace { enabled = true } } resource "google_storage_folder" "folder" { count = var.create_storage_folder ? length(var.folders) : 0 bucket = google_storage_bucket.bucket.name name = "${var.folders[count.index]}/" }
执行错误
Error: Error creating Folder: googleapi: Error 409: The parent folder does not exist., conflict │ │ with google_storage_folder.folder[3], │ on storage.tf line 12, in resource "google_storage_folder" "folder": │ 12: resource "google_storage_folder" "folder" {
即便在列表中先定义folder1再定义folder1/subfolder1,仍会触发该错误。
解决方案
问题核心是:Terraform使用count时会并行创建所有资源实例,不会严格遵循列表顺序执行。子文件夹的创建请求可能先于父文件夹完成,导致父文件夹不存在的冲突报错。
方法1:按层级深度排序+显式依赖
先对文件夹列表按路径层级深度排序,确保父文件夹排在前面,再用for_each替代count(更适配字符串集合),同时添加父文件夹的依赖关系:
locals { # 按文件夹路径的层级数量排序,父文件夹优先 sorted_folders = sort(var.folders, (a, b) => length(split("/", a)) < length(split("/", b)) ? true : false) } resource "google_storage_folder" "folder" { for_each = var.create_storage_folder ? toset(local.sorted_folders) : toset([]) bucket = google_storage_bucket.bucket.name name = "${each.value}/" # 显式依赖直接父文件夹 depends_on = [ google_storage_folder.folder[join("/", slice(split("/", each.value), 0, length(split("/", each.value)) - 1))] if length(split("/", each.value)) > 1 ] }
方法2:自动生成所有父路径(更可靠)
先解析所有文件夹的完整父路径,确保每一层级都被创建,避免遗漏:
locals { # 生成所有需要创建的文件夹(包括各级父路径) all_folders = distinct(flatten([ for folder in var.folders : [ join("/", slice(split("/", folder), 0, i)) for i in range(1, length(split("/", folder)) + 1) ] ])) } resource "google_storage_folder" "folder" { for_each = var.create_storage_folder ? toset(local.all_folders) : toset([]) bucket = google_storage_bucket.bucket.name name = "${each.value}/" # 确保直接父文件夹先被创建 depends_on = length(split("/", each.value)) > 1 ? [ google_storage_folder.folder[join("/", slice(split("/", each.value), 0, length(split("/", each.value)) - 1))] ] : [] }
这种方法会自动处理folder1/subfolder1的父路径folder1,即便变量列表中没显式写父路径,也能保证层级正确创建,同时通过depends_on严格控制执行顺序。
内容的提问来源于stack exchange,提问作者iamarunk
相关产品推荐
相关产品推荐

