合并请求中的 Terraform 集成
围绕基础架构即代码 (IaC) 更改进行协作,需要检查和批准代码更改和预期的基础架构更改。极狐GitLab 提供了一个解决方案来帮助围绕 Terraform 代码更改及其使用合并请求页面的预期效果进行协作。这样用户就不必构建自定义工具或依赖第三方解决方案来简化他们的 IaC 工作流程。
将 Terraform 计划信息输出到合并请求中
使用极狐GitLab Terraform 报告产物,您可以将 terraform plan
运行的详细信息直接公开到合并请求部件中,使您能够查看关于 Terraform 创建、修改或销毁的资源的统计信息。
配置 Terraform 报告产物
极狐GitLab 与 Terraform 集成通过使用极狐GitLab 管理的 Terraform 状态,在合并请求上显示 Terraform 更改的 CI/CD 模板。我们建议自定义预构建的镜像并依靠其中提供的 gitlab-terraform
helper 进行快速设置。
要手动配置极狐GitLab Terraform 报告产物:
-
为简单起见,让我们定义一些可重用的变量以允许我们多次引用这些文件:
variables: PLAN: plan.cache PLAN_JSON: plan.json
- 安装
jq
,一个轻量级且灵活的命令行 JSON 处理器。 -
为特定的
jq
命令创建一个别名,该命令解析出我们要从terraform plan
输出中提取的信息:before_script: - apk --no-cache add jq - alias convert_report="jq -r '([.resource_changes[]?.change.actions?]|flatten)|{\"create\":(map(select(.==\"create\"))|length),\"update\":(map(select(.==\"update\"))|length),\"delete\":(map(select(.==\"delete\"))|length)}'"
在使用 Bash 的发行版(例如 Ubuntu)中,alias
语句不会在非交互模式下展开。如果您的流水线因错误convert_report: command not found
而失败,则可以通过在脚本中添加shopt
命令来显式激活别名扩展:before_script: - shopt -s expand_aliases - alias convert_report="jq -r '([.resource_changes[]?.change.actions?]|flatten)|{\"create\":(map(select(.==\"create\"))|length),\"update\":(map(select(.==\"update\"))|length),\"delete\":(map(select(.==\"delete\"))|length)}'"
-
定义一个运行
terraform plan
和terraform show
的script
。这些命令通过流水线输出并将相关位转换为存储变量PLAN_JSON
。此 JSON 用于创建极狐GitLab Terraform 报告产物。Terraform 报告获取 Terraformtfplan.json
文件。收集的 Terraform 计划报告作为产物上传到极狐GitLab,并显示在合并请求中。plan: stage: build script: - terraform plan -out=$PLAN - terraform show --json $PLAN | convert_report > $PLAN_JSON artifacts: reports: terraform: $PLAN_JSON
有关使用预构建镜像的完整示例,请参阅示例
.gitlab-ci.yml
文件。有关显示多个报告的示例,请参阅
.gitlab-ci.yml
多个报告文件。 -
运行流水线会在合并请求中显示部件,如下所示:
-
单击小部件中的 查看完整日志 按钮可直接进入流水线日志中的计划输出:
示例 .gitlab-ci.yml
文件
default:
image: registry.gitlab.com/gitlab-org/terraform-images/stable:latest
cache:
key: example-production
paths:
- ${TF_ROOT}/.terraform
variables:
TF_ROOT: ${CI_PROJECT_DIR}/environments/example/production
TF_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/example-production
before_script:
- cd ${TF_ROOT}
stages:
- prepare
- validate
- build
- deploy
init:
stage: prepare
script:
- gitlab-terraform init
validate:
stage: validate
script:
- gitlab-terraform validate
plan:
stage: build
script:
- gitlab-terraform plan
- gitlab-terraform plan-json
artifacts:
name: plan
paths:
- ${TF_ROOT}/plan.cache
reports:
terraform: ${TF_ROOT}/plan.json
apply:
stage: deploy
environment:
name: production
script:
- gitlab-terraform apply
dependencies:
- plan
when: manual
only:
- master
多个 Terraform 计划报告
从 13.2 版本开始,您可以在合并请求页面上显示多个报告。报告还显示 artifacts: name:
。有关建议的设置,请参见下面的示例。
default:
image:
name: registry.gitlab.com/gitlab-org/gitlab-build-images:terraform
entrypoint:
- '/usr/bin/env'
- 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
cache:
paths:
- .terraform
stages:
- build
.terraform-plan-generation:
stage: build
variables:
PLAN: plan.tfplan
JSON_PLAN_FILE: tfplan.json
before_script:
- cd ${TERRAFORM_DIRECTORY}
- terraform --version
- terraform init
- apk --no-cache add jq
script:
- terraform validate
- terraform plan -out=${PLAN}
- terraform show --json ${PLAN} | jq -r '([.resource_changes[]?.change.actions?]|flatten)|{"create":(map(select(.=="create"))|length),"update":(map(select(.=="update"))|length),"delete":(map(select(.=="delete"))|length)}' > ${JSON_PLAN_FILE}
artifacts:
reports:
terraform: ${TERRAFORM_DIRECTORY}/${JSON_PLAN_FILE}
review_plan:
extends: .terraform-plan-generation
variables:
TERRAFORM_DIRECTORY: "review/"
# Review will not include an artifact name
staging_plan:
extends: .terraform-plan-generation
variables:
TERRAFORM_DIRECTORY: "staging/"
artifacts:
name: Staging
production_plan:
extends: .terraform-plan-generation
variables:
TERRAFORM_DIRECTORY: "production/"
artifacts:
name: Production