我有两个文件:一个 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
命令,我们需要通过在前面添加另一个 来“转义”它$
。
它有点笨拙(循环构造会更好,因为所有三个的解析结构基本相同),但它应该可以工作。