
簡而言之,外部數據源(不是特別推薦!) 意味著試圖從外部數據源獲取一些信息并將其呈現給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??
標簽: 外部環境