CI 缓存无法通过阶段传递提供程序配置
CI cache unable to pass provider configurations through stages
我在 terraform CI 中有通常的阶段,即 init
> validate
> plan
等。第一步,即 init
总是工作正常。
但是当我们进入下一阶段时validate
我收到以下错误:
$ terraform validate
103╷
104│ Error: Missing required provider
105│
106│ This configuration requires provider registry.terraform.io/datadog/datadog,
107│ but that provider isn't available. You may be able to install it
108│ automatically by running:
109│ terraform init
110╵
现在,如果 运行 init
与 validate
在同一阶段,它就可以正常工作。所以基本上,一种解决方法是要么在一个阶段拥有所有命令,要么在每个阶段拥有 init
,这当然都不是理想的。
如果我登录 运行ner 服务器并手动浏览 .terraform
目录,供应商 executable
就在那里。但是如果我从 shell 运行 terraform validate
它将再次失败并出现相同的错误,但是如果我 运行 init
然后 validate
现在它有效。
.terraform
目录及其内容在 init
前后没有变化。相同的文件,只是更新了创建日期时间。
如果我回到 gitlab 并重新 运行 将失败的 validate
阶段,但随后我回到服务器 shell 并执行 terraform validate
再次失败,目录内容或权限也没有明显变化。再次执行 init
,它将再次开始工作。
据我了解,这些阶段之间的唯一区别是缓存 zip/unzip,因为 .terraform
文件夹作为缓存传递。
在作业控制台中,我可以看到以下消息:
Checking cache for terraform...
Runtime platform arch=amd64 os=linux pid=3798191 revision=90daeee0 version=14.7.0
No URL provided, cache will not be downloaded from shared cache server. Instead a local version of cache will be extracted.
Successfully extracted cache
另一件需要注意的事情是,虽然下载的模块也存在于 .terraform
中,但它永远不会抛出关于模块的错误,而只会抛出关于提供者的错误。我猜它与 .exe
个文件有关?
config.toml
:
[[runners]]
name = "cicd_terraform"
url = "***"
token = "****"
executor = "shell"
[runners.custom_build_dir]
早些时候,那里有一个空的 runners.cache
部分,但情况相同,所以我将其删除。我希望它使用本地目录作为缓存。
.gitlab-ci.yml
:
cache:
key: terraform
paths:
- .terraform
before_script:
- echo -e "credentials \"$CI_SERVER_HOST\" {\n token = \"$CI_JOB_TOKEN\"\n}" > $TF_CLI_CONFIG_FILE
- cd ${TF_ROOT}
- export TF_LOG_CORE=TRACE
- export TF_LOG_PATH=${TF_ROOT}/terraform_logs.txt
- ls -al
- ls -al ${TF_ROOT}
- echo "$TF_ROOT"
stages:
- initialize
- validate
init:
stage: initialize
script:
- terraform -v
- terraform init -backend-config="*****" -backend-config="*****.tfstate" -backend-config="*****-1" -backend-config="access_key=${AWS_ACCESS_KEY_ID}" -backend-config="secret_key=${AWS_SECRET_ACCESS_KEY}" -input=false -no-color
validate:
stage: validate
script:
- terraform validate
ls -al ${TF_ROOT}/.terraform/providers/registry.terraform.io/datadog/datadog/2.24.0/linux_amd64
total 29256
drwxr-xr-x 2 gitlab-runner gitlab-runner 4096 Feb 19 01:36 .
drwxr-xr-x 3 gitlab-runner gitlab-runner 4096 Feb 19 01:36 ..
-rw-r--r-- 1 gitlab-runner gitlab-runner 48216 Feb 19 01:36 CHANGELOG.md
-rw-r--r-- 1 gitlab-runner gitlab-runner 16725 Feb 19 01:36 LICENSE
-rw-r--r-- 1 gitlab-runner gitlab-runner 12450 Feb 19 01:36 LICENSE-3rdparty.csv
-rw-r--r-- 1 gitlab-runner gitlab-runner 1524 Feb 19 01:36 README.md
-rwxr-xr-x 1 gitlab-runner gitlab-runner 29859840 Feb 19 01:36 terraform-provider-datadog_v2.24.0
知道吗,我做错了什么?
为了 Terraform 能够找到特定的提供者,必须满足两点:
- The
.terraform.lock.hcl
file 必须为该提供程序指定一个选定的版本,以及该版本允许的插件校验和。
- 在
.terraform/providers
-- 本地插件缓存目录 -- 中必须有一个与校验和之一匹配的所选版本的包。
从您分享的内容看来,其中的第二个似乎是由您使用 CI 系统的功能在步骤之间传递缓存来处理的。
为了使第一个为真,您需要在您的开发机器上 运行 terraform init
以生成 .terraform.lock.hcl
文件,然后检查该文件作为配置的一部分进入版本控制,这将有希望使您的 CI 系统将其作为检出源代码的正常部分放置在正确的位置。
When 运行ning terraform init
在这样的 non-interactive 环境中,我建议添加 -lockfile=readonly
选项,如果锁定文件与其余配置不一致。这将允许您的 CI 系统在第一步的早期就发现这个问题并且 return 一个关于它的明确错误,而在您当前的工作流程中 terraform init
可以更新锁定文件本身但是然后不会继续进行其他步骤,导致奇怪的下游错误。
我在 terraform CI 中有通常的阶段,即 init
> validate
> plan
等。第一步,即 init
总是工作正常。
但是当我们进入下一阶段时validate
我收到以下错误:
$ terraform validate
103╷
104│ Error: Missing required provider
105│
106│ This configuration requires provider registry.terraform.io/datadog/datadog,
107│ but that provider isn't available. You may be able to install it
108│ automatically by running:
109│ terraform init
110╵
现在,如果 运行
init
与validate
在同一阶段,它就可以正常工作。所以基本上,一种解决方法是要么在一个阶段拥有所有命令,要么在每个阶段拥有init
,这当然都不是理想的。如果我登录 运行ner 服务器并手动浏览
.terraform
目录,供应商executable
就在那里。但是如果我从 shell 运行terraform validate
它将再次失败并出现相同的错误,但是如果我 运行init
然后validate
现在它有效。.terraform
目录及其内容在init
前后没有变化。相同的文件,只是更新了创建日期时间。如果我回到 gitlab 并重新 运行 将失败的
validate
阶段,但随后我回到服务器 shell 并执行terraform validate
再次失败,目录内容或权限也没有明显变化。再次执行init
,它将再次开始工作。
据我了解,这些阶段之间的唯一区别是缓存 zip/unzip,因为 .terraform
文件夹作为缓存传递。
在作业控制台中,我可以看到以下消息:
Checking cache for terraform...
Runtime platform arch=amd64 os=linux pid=3798191 revision=90daeee0 version=14.7.0
No URL provided, cache will not be downloaded from shared cache server. Instead a local version of cache will be extracted.
Successfully extracted cache
另一件需要注意的事情是,虽然下载的模块也存在于 .terraform
中,但它永远不会抛出关于模块的错误,而只会抛出关于提供者的错误。我猜它与 .exe
个文件有关?
config.toml
:
[[runners]]
name = "cicd_terraform"
url = "***"
token = "****"
executor = "shell"
[runners.custom_build_dir]
早些时候,那里有一个空的 runners.cache
部分,但情况相同,所以我将其删除。我希望它使用本地目录作为缓存。
.gitlab-ci.yml
:
cache:
key: terraform
paths:
- .terraform
before_script:
- echo -e "credentials \"$CI_SERVER_HOST\" {\n token = \"$CI_JOB_TOKEN\"\n}" > $TF_CLI_CONFIG_FILE
- cd ${TF_ROOT}
- export TF_LOG_CORE=TRACE
- export TF_LOG_PATH=${TF_ROOT}/terraform_logs.txt
- ls -al
- ls -al ${TF_ROOT}
- echo "$TF_ROOT"
stages:
- initialize
- validate
init:
stage: initialize
script:
- terraform -v
- terraform init -backend-config="*****" -backend-config="*****.tfstate" -backend-config="*****-1" -backend-config="access_key=${AWS_ACCESS_KEY_ID}" -backend-config="secret_key=${AWS_SECRET_ACCESS_KEY}" -input=false -no-color
validate:
stage: validate
script:
- terraform validate
ls -al ${TF_ROOT}/.terraform/providers/registry.terraform.io/datadog/datadog/2.24.0/linux_amd64
total 29256
drwxr-xr-x 2 gitlab-runner gitlab-runner 4096 Feb 19 01:36 .
drwxr-xr-x 3 gitlab-runner gitlab-runner 4096 Feb 19 01:36 ..
-rw-r--r-- 1 gitlab-runner gitlab-runner 48216 Feb 19 01:36 CHANGELOG.md
-rw-r--r-- 1 gitlab-runner gitlab-runner 16725 Feb 19 01:36 LICENSE
-rw-r--r-- 1 gitlab-runner gitlab-runner 12450 Feb 19 01:36 LICENSE-3rdparty.csv
-rw-r--r-- 1 gitlab-runner gitlab-runner 1524 Feb 19 01:36 README.md
-rwxr-xr-x 1 gitlab-runner gitlab-runner 29859840 Feb 19 01:36 terraform-provider-datadog_v2.24.0
知道吗,我做错了什么?
为了 Terraform 能够找到特定的提供者,必须满足两点:
- The
.terraform.lock.hcl
file 必须为该提供程序指定一个选定的版本,以及该版本允许的插件校验和。 - 在
.terraform/providers
-- 本地插件缓存目录 -- 中必须有一个与校验和之一匹配的所选版本的包。
从您分享的内容看来,其中的第二个似乎是由您使用 CI 系统的功能在步骤之间传递缓存来处理的。
为了使第一个为真,您需要在您的开发机器上 运行 terraform init
以生成 .terraform.lock.hcl
文件,然后检查该文件作为配置的一部分进入版本控制,这将有希望使您的 CI 系统将其作为检出源代码的正常部分放置在正确的位置。
When 运行ning terraform init
在这样的 non-interactive 环境中,我建议添加 -lockfile=readonly
选项,如果锁定文件与其余配置不一致。这将允许您的 CI 系统在第一步的早期就发现这个问题并且 return 一个关于它的明确错误,而在您当前的工作流程中 terraform init
可以更新锁定文件本身但是然后不会继续进行其他步骤,导致奇怪的下游错误。