我想解析 Terraform vars 文件并将 TF vars 文件中的变量存储为 Makefile 中的 vars

我想解析 Terraform vars 文件并将 TF vars 文件中的变量存储为 Makefile 中的 vars

我有两个文件:一个 Terraform 变量文件 ( vars.tf) 和一个 Makefile。

我想要做的是让 Makefile“读取”Terraformvars.tf文件中的一些变量。

文件vars.tf

variable "region" {
    default = "us-west-1"
    description = "AWS Region"
}
variable "profile" {
    default = "bobs-profile"
    description = "Please enter your AWS CLI profile name"
}
variable "env" {
    default = "dev"
    description = "Please label the environment this infrastructure will be deployed to eg dev, uat, prod"
}

我希望能够调用vars.tf我的 Makefile 中的文件中列出的变量 - 这是一个简短的示例:

.ONESHELL:
.SHELL := /usr/bin/bash
.PHONY: apply plan prep
VARS="variables/$(ENV)-$(REGION).tfvars"
CURRENT_FOLDER=$(shell basename "$$(pwd)")
AWS_PROFILE"bobs-profile"

例如,我想要以下值:

  • $(ENV)
  • $(REGION)
  • $(AWS_PROFILE)

从 Terraform 文件中提取vars.tf,以便 Makefile 将使用以下变量运行:

ENV=dev
REGION=us-west-1
AWS_PROFILE=bobs-profile

有什么办法可以实现这个目标吗?

答案1

您显示的文件是用 HCL(HashiCorp 配置语言)编写的。它可以转换为 JSON,这使得使用jq.

要将 HCL 文件转换为 JSON,您可以使用诸如yj(来自https://github.com/sclevine/yj)。然后您可能已经为您jq创建了make命令:

eval "$(
    yj -cj <vars.tf |
    jq -r '
        [
            "make",
            (.variable[] | keys[]) as $key |
                "\($key)=\(.variable[][$key][].default)"
        ] | @sh'
)"

对于给定的示例,这将创建命令

'make' 'env=dev' 'profile=bobs-profile' 'region=us-west-1'

在评估时,它将运行make并将命名变量设置为提到的值。变量将采用小写形式,这正是您想要的。请注意,例如,该设置ENV可能会影响 Makefile 中 shell 命令的执行方式(ENV是 shell 中的一个特殊变量,它可能指向 shell 在启动时应获取的文件)。

您还可以获取制表符分隔列表形式的变量和值,然后在 shell 中读取:

set --

yj -cj <vars.tf |
jq -r '
    (.variable[] | keys[]) as $key |
    [ $key, .variable[][$key][].default ] |
    @tsv' |
{
    while IFS=$'\t' read -r key value; do
        set -- "$@" "$key"="$value"
    done

    make "$@"
}

这将收集位置参数列表中的变量及其值,然后make使用它们进行调用。给定问题中的文档,将执行的命令相当于

make 'env=dev' 'profile=bobs-profile' 'region=us-west-1'

作为参考,上面创建的 JSON 文档yj相当于以下内容:

{
  "variable": [
    {
      "region": [
        {
          "default": "us-west-1",
          "description": "AWS Region"
        }
      ],
      "profile": [
        {
          "default": "bobs-profile",
          "description": "Please enter your AWS CLI profile name"
        }
      ],
      "env": [
        {
          "default": "dev",
          "description": "Please label the environment this infrastructure will be deployed to eg dev, uat, prod"
        }
      ]
    }
  ]
}

答案2

假设您有 GNU make,您可以使用该shell命令将外部命令的结果分配给 Makefile 变量。

对于您的情况,您可以使用:

ENV:=$(shell awk '$$1=="variable" && $$2=="\"env\"" {i=1} $$1=="}" {i=0} i && $$1=="default" {split($$0,a,"\""); print a[2]}' test.tf)

REGION:=$(shell awk '$$1=="variable" && $$2=="\"region\"" {i=1} $$1=="}" {i=0} i && $$1=="default" {split($$0,a,"\""); print a[2]}' test.tf)

AWS_PROFILE:=$(shell awk '$$1=="variable" && $$2=="\"profile\"" {i=1} $$1=="}" {i=0} i && $$1=="default" {split($$0,a,"\""); print a[2]}' test.tf)

这将查找以 开头variable和结尾的感兴趣区域},当找到“正确”区域时设置一个标志i,如果设置了该标志并且遇到带有关键字的行default,它将提取双引号 ( ) 中的元素" ... "

请注意, double$$是必要的,因为make它将解释 的整个内容$( ... )(不考虑' ... '),并且要将文字传递$shell命令,我们需要通过在前面添加另一个 来“转义”它$

它有点笨拙(循环构造会更好,因为所有三个的解析结构基本相同),但它应该可以工作。

相关内容