1.7.1.1. 命令行配置文件(.terraformrc 或 terraform.rc)
命令行配置文件为每个用户配置了命令行的行为,适用于所有的 Terraform 工作目录,这与我们编写的 Terraform 代码是分开的。
1.7.1.1.1. 位置
配置文件的位置取决于用户使用的操作系统:
- Windows 平台上,文件名必须是 terraform.rc,位置必须在相关用户的%APPDATA%目录下。这个目录的物理路径取决于 Windows 的版本以及系统配置;在 PowerShell 中查看$env:APPDATA可以找到对应的路径
- 在其他操作系统上,文件名必须是 .terraformrc(注意第一个是.),位置必须是在相关用户的HOME目录
在 Windows 上创建配置文件时,要注意 Windows Explorer 默认隐藏文件扩展名的行为。Terraform 不会把 terraform.rc.txt 文件识别为命令行配置文件,而默认情况下 Windows Explorer 会将它的文件名显示为 terraform.rc (隐藏了扩展名的缘故)。可以在 PowerShell 或命令行中使用 dir 命令来确认文件名。
可以通过设置 TF_CLI_CONFIG_FILE 环境变量的方式来修改配置文件的位置。
1.7.1.1.2. 配置文件语法
配置文件本身如同 .tf 文件那样也采用HCL语法,但使用不同的属性和块。以下是常见语法的演示,后续的部分会详细介绍这些配置项:
plugin_cache_dir   = "$HOME/.terraform.d/plugin-cache"
disable_checkpoint = true
1.7.1.1.3. 可用配置
命令行配置文件中可以设置的配置项有:
- credentials:使用 Terraform Cloud 服务或 Terraform 企业版时使用的凭据
- credentials_helper:配置一个外部的用于读写 Terraform Cloud 或 Terraform 企业版凭据的帮助程序
- disable_checkpoint:设置为- true可以完全关闭与 Checkpoint 的交互
- disable_checkpoint_signature:设置为- true可以阻止向 Checkpoint 发送匿名 ID
- plugin_cache_dir:开启插件缓存,我们在介绍 Provider 的章节中介绍过
- provider_installation:定制化执行- terraform init时安装插件的行为
鉴于本教程无意涉及与 Terraform Cloud 或企业版相关的部分,所以我们会略过对 credentials 和 credentials_helper 的介绍;插件缓存的相关知识我们在 Provider 章节中已做过介绍,在此先偷懒略过。感兴趣的读者可以自行查阅相关文档
1.7.1.1.4. Provider 的安装
默认情况下 Terraform 从官方 Provider Registry 下载安装 Provider 插件。Provider 在 Registry 中的原始地址采用类似 registry.terraform.io/hashicorp/aws 的编码规则。通常为了简便,Terraform 允许省略地址中的主机名部分 registry.terraform.io,所以我们可以直接使用地址 hashicorp/aws。
有时无法直接从官方 Registry 下载插件,例如我们要在一个与公网隔离的环境中运行 Terraform 时。为了允许 Terraform 工作在这样的环境下,有一些可选方法允许我们从其他地方获取 Provider 插件。
1.7.1.1.4.1. 显式安装方法配置
可以在命令行配置文件中定义一个 provider_installation 块来修改 Terraform 默认的插件安装行为,命令 Terraform 使用本地的 Registry 镜像服务,或是使用一些用户修改过的插件。
通常 provider_installation 块的结构如下:
provider_installation {
  filesystem_mirror {
    path    = "/usr/share/terraform/providers"
    include = ["example.com/*/*"]
  }
  direct {
    exclude = ["example.com/*/*"]
  }
}
provider_installation 块中每一个内嵌块都指定了一种安装方式。每一种安装方式都可以同时包含 include 与 exclude 模式来指定安装方式使用的 Provider 类型。在上面的例子里,我们把所有原先位于 example.com 这个 Registry 存储中的 Provider 设置成只能从本地文件系统的 /usr/share/terraform/providers 镜像存储中寻找并安装,而其他的 Provider 只能从它们原先的 Registry 存储下载安装。
如果你为一种安装方式同时设置了 include 与 exclude,那么 exclude 模式将拥有更高的优先级。举例:包含registry.terraform.io/hashicorp/*但排除registry.terraform.io/hashicorp/dns将对所有hashicorp空间下的插件有效,但是hashicorp/dns除外。
和Terraform代码文件中Provider的source属性一样的是,在provider_installation里你也可以省略registry.terraform.io/的前缀,甚至是使用通配符时亦是如此。比如,registry.terraform.io/hashicorp/*和hashicorp/*是等价的;*/*是registry.terraform.io/*/*的缩写,而不是*/*/*的缩写。
目前支持的安装方式如下:
- direct:要求直接从原始的Registry服务下载。该方法不需要额外参数。
- filesystem_mirror:一个本地存有 Provider 插件拷贝的目录。该方法需要一个额外的参数- path来指定存有插件拷贝的目录路径。 Terraform 期待给定路径的目录内通过路径来描述插件的一些元信息。支持一下两种目录结构:- 打包式布局: HOSTNAME/NAMESPACE/TYPE/terraform-provider-TYPE_VERSION_TARGET.zip的格式指定了一个从原始 Registry 获取的包含插件的发行版 zip 文件
- 解压式布局:HOSTNAME/NAMESPACE/TYPE/VERSION/TARGET式一个包含有 Provider 插件发行版 zip 文件解压缩后内容物的目录 这两种布局下,VERSION都是代表着插件版本的字符串,比如2.0.0;TARGET则指定了插件发行版对应的目标平台,例如darwin_amd64、linux_arm、windows_amd64等等。
 
- 打包式布局: 
如果使用解压式布局,Terraform 在安装插件时会尝试创建一个到镜像目录的符号连接来避免拷贝文件夹。打包式布局则不会这样做,因为 Terraform 必须在安装插件时解压发行版文件。
你可以指定多个filesystem_mirror块来指定多个不同的目录。
- network_mirror:指定一个 HTTPS 服务地址提供 Provider 插件的拷贝,不论这些插件原先属于哪些 Registry 服务。该方法需要一个额外参数- url来指定镜像服务的地址,- url地址必须使用- https:作为前缀,以斜杠结尾。 Terraform期待该地址指定的服务实现了 Provider网络镜像协议,这是一种被设计用来托管插件拷贝的网站所需要实现的协议,在此我们不展开讨论。
需要特别注意的是,请不要使用不可信的 network_mirror 地址。Terraform 会验证镜像站点的 TLS 证书以确认身份,但一个拥有合法 TLS 证书的镜像站可能会提供包含恶意内容的插件文件。
- dev_overrides:指定使用本地的开发版本插件。有时我们想要对 Provider 代码做一些修改,为了调试本地代码编译后的插件,可以使用- dev_overrides指定使用本地编译的版本。
例如,我们想要调试本地修改过的 UCloud Provider 插件,我们可以从 github 上克隆该项目源代码,修改完代码后,编译一个可执行版本(以Mac OS为例):
$ GOOS=darwin GOARCH=arm64 go build -o bin/terraform-provider-ucloud
$ chmod +x bin/terraform-provider-ucloud
然后编写如下provider_installation配置:
provider_installation{
  dev_overrides {
    "ucloud/ucloud" = "PATH_TO_PROJECT/terraform-provider-ucloud/"
  }
}
当 Terraform 代码中要求了 source 为 ucloud/ucloud 的 Provider 时,执行 terraform init 仍然会报错,抱怨找不到 ucloud/ucloud 这个 Provider,但执行 terraform plan 或是 terraform apply 等操作时可以顺利执行,此时 Terraform 会使用路径指定的本地 Provider 插件。这种方式比较适合于调试本地 Provider 插件代码。
对于上述的几种插件安装方式,Terraform 会尝试通过 include 和 exclude 模式匹配 Provider,遍历匹配的安装方式,选择一个符合 Terraform 代码中对插件版本约束的最新版本。如果你拥有一个插件的特定版本的本地镜像,并且你希望 Terraform 只使用这个本地镜像,那么你需要移除 direct 安装方式,或是在 direct 中通过exclude 参数排除特定的 Provider。
1.7.1.1.5. 隐式的本地镜像目录
如果命令行配置文件中没有包含 provider_installation 块,那么 Terraform 会生成一个隐式的配置。该隐式配置包含了一个 filesystem_mirror 方法以及一个 direct 方法。
在不同的操作系统上,Terraform 会选择不同的路径作为隐式 filesystem_mirror 路径:
- Windows:%APPDATA%/terraform.d/plugins以及%APPDATA%/HashiCorp/Terraform/plugins
- Mac OS X:$HOME/.terraform.d/plugins/,~/Library/Application Support/io.terraform/plugins以及/Library/Application Support/io.terraform/plugins
- Linux 以及其他 Unix 风格系统:$HOME/.terraform.d/plugins/,以及配置的 XDG 基础目录后接terraform/plugins。如果没有设置 XDG 环境变量,Terraform 会使用~/.local/share/terraform/plugins,/usr/local/share/terraform/plugins,以及/usr/share/terraform/plugins
Terraform 会在启动时为上述路径的每一个目录创建一个隐式 filesystem_mirror 块。另外如果当前工作目录下包含有 terraform.d/plugins 目录,那么也会为它创建一个隐式 filesystem_mirror 块。
相对于任意多个隐式 filesystem_mirror 块,Terraform 同时也会创建一个隐式 direct 块。Terraform 会扫描所有文件系统镜像目录,对找到的 Provider 自动从 direct 块中排除出去(这种自动的 exclude 行为只对隐式 direct 块有效。如果你在 provider_installation 块中显式指定了 direct 块,那么你需要自己显式定义 exclude 规则)。
TODO:https://developer.hashicorp.com/terraform/cli/config/config-file#provider-plugin-cache