如何将环境变量从.env文件读入terraform脚本?

如何将环境变量从.env文件读入terraform脚本?,terraform,Terraform,我正在用terraform在aws上构建一个lambda函数。terraform脚本中用于上载环境变量的语法为: resource "aws_lambda_function" "name_of_function" { ... environment { variables = { foo = "bar" } } } 现在我的repo中有一个.env文件,其中包含一系列变量,例如email=admin@example.com“,我希望terra

我正在用terraform在aws上构建一个lambda函数。terraform脚本中用于上载环境变量的语法为:

resource "aws_lambda_function" "name_of_function" {

  ...

  environment {
    variables = {
      foo     = "bar"
    }
  }
}

现在我的repo中有一个
.env
文件,其中包含一系列变量,例如
email=admin@example.com“
,我希望terraform从该文件中读取(部分)它们,并将它们注入到环境变量的空间中,以便上传并提供给lambda函数。如何做到这一点?

我最终编写了一个简单的PHP脚本来读取env文件,按照我的意愿解析它(
explode()
,删除带有“#”的行,没有其他变量等,然后再次
implode()
),然后首先在我的makefile中评估它。看起来像这样:

provision:
    @eval $(php ./scripts/terraform-env-vars.php); \
    terraform init ./deployment/terraform; \
    terraform apply -auto-approve ./deployment/terraform/

不幸的是,terraform有一个荒谬的想法

我通过组合使用
grep
sed
解决了这个问题,我的想法是使用regex将所有环境变量替换为所需的前缀

首先,您需要声明一个与.tf文件中的环境变量同名的:

variable "MY_ENV_VAR" {
  type = string
}
然后,在执行terraform命令之前,请使用以下命令:

export$(shell sed-E的/(.*)/TF_VAR_1;1/“my.env|grep-v”#“| grep-v”TF_VAR_$”;地形应用

它的作用是:

  • 使用
    sed
    获取具有
    (.*)
    的捕获组中的每一行,然后在替换前缀
    TF\u VAR
    中获取第一个捕获组(
    \1
  • 使用grep删除所有有注释的行(任何带有
    的行)
  • 使用grep删除只有
    TF\u VAR
    的所有行

不幸的是,这也有一大堆其他的环境变量,前缀是
TF_VAR
,我不知道为什么,但这至少是在terraform中使用
.env
文件的一个开始。

我现在的解决方案包括3个点/步骤

  • 将变量放置在.env文件中,如下所示:
  • 是的,你不得不在vars前面加上
    TF\u VAR\uu
    ,这有点让人恼火,但我已经学会了接受它(至少它在你的.env中明确了terraform将使用哪些vars,哪些不会)

  • 在TF脚本中,您必须声明任何这样的变量,而不使用
    TF\u VAR
    前缀。例如
  • 在运行terraform之前,您需要对.env文件(
    .env
    )进行源代码分析,以便任何此类变量都可用于您希望在当前shell环境(即此处的terraform)中启动的进程。添加这一步并不困扰我,因为我总是用bash脚本操作我的repo

  • 注意:我提出了一个更好的方法来处理.env文件的请求,尽管我现在对现状非常满意(官方文档中对TF与.env文件的关系描述得很差)。

    我喜欢python,我不喜欢污染我的环境变量,我使用了python3虚拟环境和
    pythondotev[cli]
    包。我知道在其他语言中也有dotenv,这些可能也适用

    这就是我所做的

    在我的Mac上看起来像这样

    设置虚拟环境、激活虚拟环境、安装软件包 将环境变量放入本地目录中的
    .env
    文件中 然后,在运行terraform时,使用dotenv cli前缀
    dotenv运行地形平面图

    当您完成虚拟环境时
    停用

    若要在以后重新开始,请从TF目录
    source-venv/bin/activate


    这使我可以在运行其他TF时加载环境变量,而无需存储它们。

    基于@joe jacobs的建议,避免在所有变量前加上
    TF\u VAR
    前缀,用优秀的
    https://github.com/cloudposse/tfenv
    实用程序

    这意味着您可以将变量定义为
    .env文件
    中的
    FOO=bar
    ,以便将其用于其他目的

    然后运行如下命令:

    dotenv run tfenv terraform plan
    

    Terraform将能够找到设置为
    bar
    的环境变量
    TF\u VAR\u FOO
    这是一个纯地形解决方案,它将
    .env
    文件解析为本地地形地图

    output "foo" {
      value = { for tuple in regexall("(.*)=(.*)", file("/path/to/.env")) : tuple[0] => tuple[1] }
    }
    

    我已将其定义为通过CLI进行快速测试的输出,但您始终可以将其定义为本地变量或直接在参数上进行测试。

    是否可以使用a并将其视为标准地形变量?基本语法仍然是key/value pairs,但是我必须在repo中维护两个文件(和两个模板):.env和.tfvars:(这个问题因为一些无关紧要的措辞原因而结束了(IMO).如果/当投票决定重新开放时,我有一个解决方案。嘿@Magnus,你找到比我发布的更好的解决方案了吗?@Jimbo好的--完成了..只是注意到“导出TF\u FOO”对我不起作用,但“导出TF\u VAR\u FOO”是的。@Amir Agh——这是一个愚蠢/恼人的错误。我显然写得很草率。事实上,我的.env文件中的所有变量都有前缀TF_VAR_。我现在已经更正了答案。谢谢!我真的很喜欢这个,首先是因为它是terraform native,其次是因为它是“添加并忘记”。这是一个很好的解决方案。
    python3 -m venv venv
    source venv/bin/activate
    pip install "python-dotenv[cli]"
    
    foo1 = "bar1"
    foo2 = "bar2"
    
    dotenv run tfenv terraform plan
    
    output "foo" {
      value = { for tuple in regexall("(.*)=(.*)", file("/path/to/.env")) : tuple[0] => tuple[1] }
    }