
Terragrunt 隐藏文件夹拷贝机制解析为何下载远端配置时会跳过 .git 与 .terraform【免费下载链接】terragruntTerragrunt is a flexible orchestration tool that allows Infrastructure as Code written in OpenTofu/Terraform to scale.项目地址: https://gitcode.com/GitHub_Trending/te/terragruntTerragrunt 在执行terraform/tofu命令前会把terraform { source }指向的远端 Terraform 配置下载并拷贝到本地临时目录如.terragrunt-cache拷贝时默认会跳过所有以点号开头的隐藏文件夹。本文以仓库中专门用于回归验证该行为的测试夹具 local-with-hidden-folder 下的说明文档 为主线结合 internal/util/file.go 的底层拷贝实现与 integration_download_tf_test.go 的集成测试讲清楚隐藏目录过滤的原理、为何用只读文件做“探测”、以及如何通过include_in_copy/exclude_from_copy打破默认规则。一个特殊测试夹具.hidden-folder/README.md的用意在test/fixtures/download/目录下几乎每个子目录都对应一类“下载远端配置”的测试场景其中local-with-hidden-folder专门用于验证隐藏文件夹不被拷贝。该夹具的结构为test/fixtures/download/local-with-hidden-folder/ ├── .hidden-folder/ │ └── README.md # 内容见下文 └── terragrunt.hcl # source ../hello-world夹具内的 terragrunt.hcl 极其简洁只声明了一个inputs和指向../hello-world的sourceinputs { name World } terraform { source ../hello-world }而被放置在隐藏目录里的 .hidden-folder/README.md 则说明了两点关键信息这是一个“隐藏文件夹”以点号开头用于验证 Terragrunt不会把.git、.terraform这类隐藏目录拷贝到下载临时目录该文件被故意设置为只读权限一旦它被错误地拷贝进临时目录第二次运行 Terragrunt 时就会因尝试覆盖这个只读文件而报错退出。为什么用“只读文件”来做探测这正是这套回归测试的设计巧思——它把“隐藏文件是否被误拷贝”这个难以直接断言的状态转换成了“第二次运行时是否报错”这个可观测的行为属于典型的故障注入式测试fault injection手法。底层原理TerragruntExcludes的隐藏目录判定隐藏文件夹不被拷贝并非巧合而是由 internal/util/file.go 中的TerragruntExcludes函数在拷贝遍历时强制保证的func TerragruntExcludes(path string) bool { if filepath.Base(path) TerraformLockFile { return false } pathParts : strings.SplitSeq(path, string(filepath.Separator)) for pathPart : range pathParts { if strings.HasPrefix(pathPart, .) pathPart ! . pathPart ! .. { return true } } return false }该函数对路径做逐段扫描只要路径的任意一级目录名以.开头且不是.、..这两个特殊目录整个路径就会被判定为“排除”。也就是说.git/、.terraform/、.hidden-folder/、.terraform.lock.hcl这类以点号开头的条目默认一律跳过唯一例外是TerraformLockFile即.terraform.lock.hcl定义见 internal/util/file.go因为它是 Terraform/OpenTofu 依赖锁定文件Terragrunt 需要把它一并拷贝到临时目录才能保证锁定的依赖版本可复现。因此从实现层面看local-with-hidden-folder夹具中的.hidden-folder/与真实场景里的.git/、.terraform/走的是完全相同的过滤逻辑——它们都命中TerragruntExcludes在拷贝阶段被直接跳过。拷贝主流程CopyFolderContents与可配置选项隐藏目录过滤发生在 Terragrunt 把模块源码复制到临时目录的核心函数 CopyFolderContents 中。该函数在注释里就明确写着“hidden files and folders (those starting with a dot) will be skipped”以点号开头的隐藏文件与目录将被跳过。// CopyFolderContents copies the files and folders within the source folder into // the destination folder. Note that hidden files and folders (those starting // with a dot) will be skipped. Will create a specified manifest file that // contains paths of all copied files. // // Optional behavior is configured through [CopyOption] values such as // [WithIncludeInCopy], [WithExcludeFromCopy], and [WithFastCopy]. func CopyFolderContents(...) error拷贝行为由一组CopyOption控制它们直接映射到 Terragrunt HCL 中的配置项CopyOption对应 HCL 配置作用WithIncludeInCopy(patterns...)include_in_copy即使命中TerragruntExcludes也会被强制拷贝例如显式放行某个隐藏文件WithExcludeFromCopy(patterns...)exclude_from_copy在默认排除的基础上追加 glob 排除规则WithFastCopy()fast-copy严格模式strict control启用并行快速拷贝路径glob 只编译一次、源码树只遍历一次WithSymlinkedGlobRoots()symlinks实验特性让以符号链接目录为根的 include/exclude glob 能穿透链接展开匹配对应 issue #6791其中WithExcludeFromCopy对应的exclude_from_copy是terragrunt.hcl里最常用的配置之一用于把默认不排除的额外文件/目录排除掉terraform { source git::gitgithub.com:acme/modules.git//networking exclude_from_copy [ **/*.md, **/docs/**, ] }过滤模式会被 compileExcludePattern 编译为 glob 匹配器后参与拷贝判定。如何在默认规则之外放行隐藏文件include_in_copy默认跳过隐藏文件并非绝对。若某个隐藏文件确实对模块运行必不可少例如版本戳.nonce、密钥占位文件、仅存于隐藏目录中的配置可以在terragrunt.hcl中通过include_in_copy显式放行。仓库中的local-with-allowed-hidden夹具就是为此准备的。其 live/terragrunt.hcl 演示了精确放行单个隐藏文件的写法terraform { source ../modules include_in_copy [.nonce] }对应地internal/util/file.go 中WithIncludeInCopy的实现注释印证了这一点该选项用于把即使被TerragruntExcludes跳过也会被拷贝的模式加进来adds glob patterns that must be copied even when TerragruntExcludes would skip them。底层判定逻辑internal/util/file.go 一带采用“先应用默认排除再应用 include 白名单”的顺序当某路径既命中TerragruntExcludes又命中include_in_copy时以 include 的显式声明为准将其放行。集成测试如何验证这套行为仓库把上述机制固化成了两个端到端集成测试均位于 test/integration_download_tf_test.go1.TestTFLocalDownloadWithHiddenFolder隐藏目录不得被拷贝func TestTFLocalDownloadWithHiddenFolder(t *testing.T) { t.Parallel() tmpEnvPath : helpers.NewGitServer(t).RenderFixture(fixtures/download) rootPath : filepath.Join(tmpEnvPath, testFixtureLocalWithHiddenFolder) helpers.CleanupTerraformFolder(t, rootPath) helpers.RunTerragrunt( t, terragrunt apply -auto-approve --non-interactive --working-dir rootPath, ) // Run a second time to make sure the temporary folder can be reused without errors helpers.RunTerragrunt( t, terragrunt apply -auto-approve --non-interactive --working-dir rootPath, ) }测试连续运行两次terragrunt apply第一次运行拷贝源../hello-world到临时目录.hidden-folder/被TerragruntExcludes跳过因此只读的README.md从未进入临时目录第二次运行临时目录被复用缓存命中若第一次误拷贝了只读文件此时覆盖操作就会触发“attempt to overwrite a read-only file”错误测试随即失败。两次运行都能成功通过即证明隐藏文件夹在整个下载-拷贝-复用生命周期中始终被正确排除。这也正呼应了夹具 README 中对测试意图的原始描述。2.TestTFLocalDownloadWithAllowedHiddenFilesinclude_in_copy 放行隐藏文件// CopyFolderContents skips hidden files; the fixtures modules/.nonce is required for the apply. noncePath : filepath.Join(rootPath, modules, .nonce) require.NoError(t, os.WriteFile(noncePath, []byte(Hello world\n), 0600))测试先在modules/下手动创建一个隐藏文件.nonce模块 apply 所必需再通过live/terragrunt.hcl里的include_in_copy [.nonce]放行它最后执行terragrunt apply与terragrunt output -raw text断言输出值验证.nonce确实被拷贝到了临时目录。两个测试一正一反完整覆盖了“默认跳过”与“显式放行”两种行为。实践要点与排查建议结合上述源码与测试在实际使用 Terragrunt 时可以参考以下几点不要把运行时状态放进隐藏目录.git/、.terraform/等以点号开头的目录默认不会进入.terragrunt-cache这是刻意设计——避免把 VCS 元数据、Provider 缓存这类大而无关的内容反复拷贝、拖慢每次执行的准备阶段。模块必须依赖的隐藏文件用include_in_copy精确放行粒度越细越好尽量写成明确的 glob 模式如.nonce、.secrets/**避免用宽泛模式把整个隐藏目录放进来否则会失去隐藏过滤带来的性能与整洁性收益。希望额外排除非隐藏文件用exclude_from_copy如文档、示例、CI 配置等可减少拷贝体积。遇到“只读文件被覆盖报错”时优先怀疑拷贝范围若你自定义过include_in_copy且放宽到覆盖了只读文件第二次运行就可能出现覆盖失败——这正是local-with-hidden-folder夹具 README 所描述的故障模式把include_in_copy收窄到真正必要的文件即可。锁文件是例外.terraform.lock.hcl不受隐藏过滤影响会被正常拷贝确保依赖锁定在临时目录中依然生效。小结test/fixtures/download/local-with-hidden-folder/.hidden-folder/README.md虽然只是一份几行的说明文档但它精准概括了 Terragrunt 下载远端配置时一条至关重要的默认行为所有以点号开头的隐藏目录在拷贝阶段一律跳过。这条规则由 internal/util/file.go 的TerragruntExcludes逐段扫描实现由CopyFolderContents在每次模块拷贝时强制执行并通过“只读文件 二次运行”的巧妙设计与include_in_copy/exclude_from_copy的正反用例固化为可重复的集成测试。理解这套机制有助于你在编排多模块基础设施时准确预判.terragrunt-cache里会有什么、不会有什么以及何时需要显式放行隐藏文件。【免费下载链接】terragruntTerragrunt is a flexible orchestration tool that allows Infrastructure as Code written in OpenTofu/Terraform to scale.项目地址: https://gitcode.com/GitHub_Trending/te/terragrunt创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考