简而言之,外部数据源(不是特别推荐!) 意味着试图从外部数据源获取一些信息并将其呈现给Terraform。Terraform外部数据源执行shell脚本或python或任何其他程序。Terraform像使用其他数据源一样使用程序的输出。这意味着外部数据源为Terraform提供了一种与外部世界交互的方式。这是非常有用的!
注意: 外部数据源与AWS、Azure或谷歌云提供商或任何其他云提供商无关。
如上所述的外部数据源允许Terraform与外部环境进行数据交互。那么这里的捕获信息是什么(这里总是有一个捕获信息),程序的输入和输出必须是JSON对象。要通过shell脚本使用Terraform外部数据源,您最好了解 jq。
(相关资料图)
注意:外部数据源允许Terraform与外部环境进行交互。敲黑板,所有必需的软件都要事先安装好,否则以后可能会出现令人讨厌的意外。只有当你在Terraform 中找不到解决方案时才使用它。
一个潜在的用例-我发现这很有用(您可能不同意),当获取有关AWS(或任何其他云)资源的信息时,Terraform数据资源没有提供有关该云资源的所有信息。例如,用于Kafka的AWS Managed Service的Terraform数据资源没有为代理提供子网信息(至少在我写代码之前没有)。尽管这些信息可以通过AWS CLI或boto库获得。
这里没有太多参数可以传递给外部数据源,只有两个!
外部数据源参数 | 描述 |
程序 | Python 或 shell 的可执行程序 |
查询 | 作为JSON传递给程序的变量 |
注意: 程序被 locally 所执行
最后,这里是我们博客的一个用例,我们想根据传递给shell脚本的environment 和url这两个参数返回ip地址和端口。这些信息在Terraform中是不可用的,因为它总是神奇地变化;)。在我们继续之前,shell脚本和python的示例几乎都做同样的事情,只是为了说明这篇文章的目的。
让我们看看如何通过调用shell脚本获取terrraform外部数据源。将执行以下步骤
创建一个shell脚本从Terraform外部数据源调用shell脚本向它传递一些参数并进行一些处理。处理完成后,脚本将输出作为JSON对象返回到terraform。
注意: 确保您已经安装了jq,除非您想手动处理JSON对象,同时安装您的shell脚本任何其他库/包。
我们的terrraform脚本ext_data_source.tf是非常简单的,它调用shell脚本get_ip_port.sh,并传递一个参数p_env,它的值是dev。现在,这个值可以是其他任何东西,作为Terraform提供的资源的一部分,它是动态生成的!!
data "external" "get_ip_addres_using_shell_dev" { program = ["bash","scripts/get_ip_port.sh"] query = { p_env = "dev" }}output "ip_address_for_dev" { value = data.external.get_ip_addres_using_shell_dev.result.ip_address}output "port_num_for_dev" { value = data.external.get_ip_addres_using_shell_dev.result.port_num}
#!/bin/bash# Step#0 - Magical list of ip addresses and ports which cannot exist in terraformdeclare -A test_vartest_var["dev"]="10.0.0.1:8081"test_var["qa"]="10.0.0.2:8082"test_var["uat"]="10.0.0.3:8083"test_var["stage"]="10.0.0.4:8084"test_var["prod"]="10.0.0.5:8085"# Step#1 - Parse the inputeval "$(jq -r "@sh "p_env=\(.p_env)"")"# Step#2 - Extract the ip address and port number based on the key passedurl_str=${test_var[$p_env]}arr=(${url_str//:/ })IP_ADDRESS=${arr[0]}PORT_NUM=${arr[1]}# Step#3 - Create a JSON object and pass it backjq -n --arg ip_address "$IP_ADDRESS" \ --arg port_num "$PORT_NUM" \ "{"ip_address":$ip_address, "port_num":$port_num}"
让我们简单看一下shell脚本的逻辑
Step#1 – 输入解析为 JSON,数据被提取到一个名为 p_env 的变量中Step#2 – 变量p_dev用于从hashmap中提取ip地址和端口号Step#3 – 使用 jq 返回包含 ip 地址和端口号的 JSON 对象
让我们看一下运行terrraform apply 之后的输出
Do you want to perform these actions? Terraform will perform the actions described above. Only "yes" will be accepted to approve. Enter a value: yesApply complete! Resources: 0 added, 0 changed, 0 destroyed.Outputs:ip_address_for_dev = "10.0.0.1"port_num_for_dev = "8081"
我们的terrraform脚本ext_data_source.tf非常简单,它调用Python脚本get_ip_port.py,并传递一个值为qa到参数p_env。正如您所看到的,这与前一节中的非常相似。
data "external" "get_ip_addres_using_python" { program = ["python3","scripts/get_ip_port.py"] query = { p_env = "qa" }}output "ip_address_for_qa" { value = data.external.get_ip_addres_using_python_dev.result.ip_address}output "port_num_for_qa" { value = data.external.get_ip_addres_using_python_dev.result.port_num}
import sysimport json# Magical list of ip addresses and ports which cannot exist in terraformtest_var = dict()test_var["dev"] = "10.0.0.1:8081"test_var["qa"] = "10.0.0.2:8082"test_var["uat"] = "10.0.0.3:8083"test_var["stage"] = "10.0.0.4:8084"test_var["prod"] = "10.0.0.5:8085"# Step#1 - Parse the inputinput = sys.stdin.read()input_json = json.loads(input)# Step#2 - Extract the ip address and port number based on the key passedarr = test_var[input_json.get("p_env")].split(":")ip_address = arr[0]port_num = arr[1]# Step#3 - Create a JSON object and just print it(i.e send it to stdout)output = { "ip_address": ip_address, "port_num": port_num}output_json = json.dumps(output,indent=2)print(output_json)
下面是在python脚本中完成的步骤的概述,这些步骤与前一节中的shell脚本非常相似
Step#1 – 输入解析Step#2 – 从字典中提取ip地址和端口号Step#3 – 返回包含ip地址和端口号的JSON对象
让我们看一下运行terrraform apply 之后的输出
Do you want to perform these actions? Terraform will perform the actions described above. Only "yes" will be accepted to approve. Enter a value: yesApply complete! Resources: 0 added, 0 changed, 0 destroyed.Outputs:ip_address_for_dev = "10.0.0.2"port_num_for_dev = "8082"
从上面可以看出,外部数据源是将Terraform与外部环境连接起来的非常有用的工具。显然也不难理解。希望你觉得这篇文章有用。如果你喜欢它,请分享它并传播知识!
源文章https://www.cloudwalker.io/2021/10/09/terraform-external-data-source/
License:Attribution-NonCommercial-ShareAlike 4.0 International
本文出自Suzf Blog。 如未注明,均为 SUZF.NET 原创。
转载请注明:https://suzf.net/post/1459
标签: 外部环境