Fork me on GitHub
Suzf  Blog

Terraform – External Data Source

前言

简而言之,外部数据源(不是特别推荐!) 意味着试图从外部数据源获取一些信息并将其呈现给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 脚本

让我们看看如何通过调用shell脚本获取terrraform外部数据源。将执行以下步骤

创建一个shell脚本
从Terraform外部数据源调用shell脚本
向它传递一些参数并进行一些处理。
处理完成后,脚本将输出作为JSON对象返回到terraform。

注意: 确保您已经安装了jq,除非您想手动处理JSON对象,同时安装您的shell脚本任何其他库/包。

 

Terraform 脚本

我们的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
}

Shell 脚本

#!/bin/bash
# Step#0 - Magical list of ip addresses and ports which cannot exist in terraform
declare -A test_var
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 input
eval "$(jq -r '@sh "p_env=\(.p_env)"')"
# Step#2 - Extract the ip address and port number based on the key passed
url_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 back
jq -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: yes

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
ip_address_for_dev = "10.0.0.1"
port_num_for_dev = "8081"

 

外部数据源 & Python

Terraform 脚本

我们的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
}

Python Script

import sys
import json
# Magical list of ip addresses and ports which cannot exist in terraform
test_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 input
input = sys.stdin.read()
input_json = json.loads(input)
# Step#2 - Extract the ip address and port number based on the key passed
arr = 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: yes

Apply 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

「一键投喂 软糖/蛋糕/布丁/牛奶/冰阔乐!」

Suzf Blog

(๑>ڡ<)☆ 谢谢 ~

使用微信扫描二维码完成支付