我的项目使用 Terraform 来设置 CI/CD 的基础设施和 Github Actions。运行后
terraform apply
我想将 Terraform 输出变量的值保存为 Github Action 环境变量,以供工作流程稍后使用。
根据 Github Action 的文档,this 是使用工作流命令创建或更新环境变量的方法。
这是我简化的 Github Action 工作流程:
name: Setup infrastructure
jobs:
run-terraform:
name: Apply infrastructure changes
runs-on: ubuntu-latest
steps:
...
- run: terraform output vm_ip
- run: echo TEST=$(terraform output vm_ip) >> $GITHUB_ENV
- run: echo ${{ env.TEST }}
在本地运行时,命令
echo TEST_VAR=$(terraform output vm_ip)
准确输出 TEST="192.168.23.23"
但从 Github Action CLI 输出中我得到了一些非常奇怪的东西:
我尝试过使用单引号、双引号。在某些时候我改变了策略并尝试使用
jq
。因此,我添加了以下步骤,以便将所有 Terraform 输出导出到 json 文件并使用 jq
: 解析它
- run: terraform output -json >> /tmp/tf.out.json
- run: jq '.vm_ip.value' /tmp/tf.out.json
但是现在它抛出以下错误:
parse error: Invalid numeric literal at line 1, column 9
即使生成的 JSON 完全有效:
{
"cc_host": {
"sensitive": false,
"type": "string",
"value": "private.c.db.ondigitalocean.com"
},
"cc_port": {
"sensitive": false,
"type": "number",
"value": 1234
},
"db_host": {
"sensitive": false,
"type": "string",
"value": "private.b.db.ondigitalocean.com"
},
"db_name": {
"sensitive": false,
"type": "string",
"value": "XXX"
},
"db_pass": {
"sensitive": true,
"type": "string",
"value": "XXX"
},
"db_port": {
"sensitive": false,
"type": "number",
"value": 1234
},
"db_user": {
"sensitive": false,
"type": "string",
"value": "XXX"
},
"vm_ip": {
"sensitive": false,
"type": "string",
"value": "206.189.15.70"
}
}
命令
terraform output -json >> /tmp/tf.out.json
和 jq '.vm_ip.value' /tmp/tf.out.json
在本地相应地工作。
经过几个小时的搜索,我终于弄清楚了。
似乎 Terraform 的 Github Action 提供了一个名为
terraform_wrapper
的附加参数,如果您计划在命令中使用输出,则需要将其设置为 false
。您可以阅读更深入的文章这里。
否则,它们将自动暴露给步骤的输出,并且可以像
steps.<step_id>.outputs.<variable>
一样访问它们。您可以在此处和此处阅读有关它们的更多信息。
这真是一头野兽!在尝试了上述方法之后,我无法让任何东西发挥作用,因此将所有内容缝合在一起,我终于能够找到一种不使用任何扩展的方法。
这是我的 Terraform 应用:
- name: 'Terraform_Apply'
id: tfapply
if: github.ref == 'refs/heads/master'
uses: hashicorp/terraform-github-actions@master
with:
tf_actions_version: 1.4.6
tf_actions_subcommand: 'apply'
tf_actions_working_dir: "./Admin/Infrastructure"
steps.tfapply.outputs.login_server 对我不起作用。
我正在使用 tf_actions_version 1.4.6,并使用 terraform_wrapper: true 和 false 进行了尝试。然而,最终起作用的是将 terraform_wrapper 设置为 false 并添加此中间步骤:
- name: 'Set vars'
id: vars
run: |
printf "login_server=%s\n" $(terraform -chdir="./Admin/Infrastructure" output -raw login_server) >> "$GITHUB_OUTPUT"
printf "admin_username=%s\n" $(terraform -chdir="./Admin/Infrastructure" output -raw admin_username) >> "$GITHUB_OUTPUT"
printf "admin_password=%s\n" $(terraform -chdir="./Admin/Infrastructure" output -raw admin_password) >> "$GITHUB_OUTPUT"
我使用 -chdir 因为我的 Dockerfile 位于主解决方案的子目录中,如果您不需要格式化任何内容,也可以在此处使用 echo。
然后,变量显示时不带引号(感谢 -raw),我可以在后面的步骤中访问它们:
- name: 'Set Azure Login for ACR'
uses: azure/docker-login@v1
with:
login-server: ${{steps.vars.outputs.login_server}}
username: ${{steps.vars.outputs.admin_username}}
password: ${{steps.vars.outputs.admin_password}}
这让我可以从 Terraform 创建 ACR,然后获取这些值,以便我可以使用它们将构建映像直接推送到 ACR。
为了完整性,这是我的 Terraform。
resource "azurerm_container_registry" "acr" {
name = "devportalacr"
resource_group_name = azurerm_resource_group.rg.name
location = "eastus2"
sku = "Basic"
admin_enabled = true
tags = {
Environment = "production"
}
}
output login_server {
value = azurerm_container_registry.acr.login_server
}
output admin_username {
value = azurerm_container_registry.acr.admin_username
}
output admin_password {
sensitive = true
value = azurerm_container_registry.acr.admin_password
}
在出现此错误几天后,我使用了这个并且它起作用了
- name: 'Set up Terraform'
uses: hashicorp/setup-terraform@v1
with:
terraform_wrapper: false
terraform_version: 1.0.11
- name: Capture Terraform Outputs
run: |
EC2_PUBLIC_IP=$(terraform output -raw ec2_public_ip 2>/dev/null || echo "")
EC2_PRIVATE_KEY=$(terraform output -raw ec2_private_ip 2>/dev/null || echo "")
# Append outputs to GitHub environment
echo "EC2_PUBLIC_IP=$EC2_PUBLIC_IP" >> $GITHUB_ENV
echo "EC2_PRIVATE_KEY=$EC2_PRIVATE_KEY" >> $GITHUB_ENV