写点什么

带你掌握利用 Terraform 不同数据源扩展应用场景

  • 2023-07-17
    广东
  • 本文字数:2644 字

    阅读完需:约 9 分钟

带你掌握利用Terraform不同数据源扩展应用场景

本文分享自华为云社区《利用Terraform不同数据源扩展应用场景》,作者: kaliarch 。

一 背景


在生产环境中使用 Terraform 进行基础设施编排,通常又一些信息是通过其他外部系统传入,该场数据源为一个接口,需要 Terraform 具备调用远程接口能力,获取数据进行目标资源编排,处理各种云厂商提供的 provider 接口 data 数据类型外,terraform 社区还具备 http provider,利用此可以进行调用第三方外部系统接口,实现自助外部接口获取编排。


除了 Terraform 直接通过调用 http provider 接口获取数据外,还可以使用执行本地 Shell/Python 脚本,脚本内部实现调用外部接口获取数据,再将数据进行传入到 Terraform 进行使用。

二 原理

2.1 数据源概念


数据源允许获取和计算数据,以便在代码中使用。源可以位于另一个 Terraform 配置中或外部。与资源相反,数据源不由 Terraform 管理。

2.2 数据源优势


  • 减少模块之间的耦合,并使用您的基础设施作为事实的来源。

  • 通过减少变量的数量来隐藏 Terraform 最终用户的复杂性

2.3 扩展数据源方式

2.3.1 http


terraform 下载 http provider,其内部为一个 go 编写的 http 客户端,可以实现调用外部接口。

https://registry.terraform.io/providers/hashicorp/http/latest/docs

2.3.2 脚本方式


terraform 扮演执行器,利用 external provider 进行执行各脚本语言,实现执行脚本内容达到预定目标。

三 http 数据源

3.1 测试场景


使用 Terraform 编写编排文件,获取 github 个人资料信息。

3.2 代码


  • 目录结构


├── main.tf // 主文件
├── outputs.tf // 输出文件
└── variables.tf // 变量文件
复制代码


  • 代码内容


# main.tf
data "http" "get_method" {
url = "https://api.github.com/users/${var.gitName}"
request_headers = {
Accept = "application/json"
}
}
data "http" "post_method" {
url = "https://checkpoint-api.hashicorp.com/v1/check/terraform"
method = "POST"
# Optional request body
request_body = "request body"
}
# variables.tf
variable "gitName" {
type = string
default = "redhatxl"
}
# outputs.tf
output "resp" {
value = {
get = data.http.get_method.body
post = data.http.post_method.body
}
}
复制代码

3.3 测试


# init
$ terraform init
# plan
$ terraform plan
# 将输出文件到处到json文件中
$ terraform show --json github.out | > redhatxl.json
# apply应用
$ terraform apply
复制代码


3.4 其他

3.4.1 POST 请求


data "http" "example_post" {
url = "https://checkpoint-api.hashicorp.com/v1/check/terraform"
method = "POST"
# Optional request body
request_body = "request body"
}
复制代码

3.4.2 后置条件


data "http" "example" {
url = "https://checkpoint-api.hashicorp.com/v1/check/terraform"
# Optional request headers
request_headers = {
Accept = "application/json"
}
lifecycle {
postcondition {
condition = contains([201, 204], self.status_code)
error_message = "Status code invalid"
}
}
}
复制代码

3.4.3 前置条件


data "http" "example" {
url = "https://checkpoint-api.hashicorp.com/v1/check/terraform"
# Optional request headers
request_headers = {
Accept = "application/json"
}
}
resource "random_uuid" "example" {
lifecycle {
precondition {
condition = contains([201, 204], data.http.example.status_code)
error_message = "Status code invalid"
}
}
}
复制代码

3.4.4 使用 Provisioner


data "http" "example" {
url = "https://checkpoint-api.hashicorp.com/v1/check/terraform"
# Optional request headers
request_headers = {
Accept = "application/json"
}
}
resource "null_resource" "example" {
# On success, this will attempt to execute the true command in the
# shell environment running terraform.
# On failure, this will attempt to execute the false command in the
# shell environment running terraform.
provisioner "local-exec" {
command = contains([201, 204], data.http.example.status_code)
}
}
复制代码

四 脚本执行


“外部数据源允许实现特定协议(定义如下)的外部程序充当数据源,公开任意数据以供 Terraform 配置中的其他地方使用。”


有时,我的 terraform 模块依赖于不是由 terraform 提供者管理的数据,而是由我的存储库中的构建步骤或脚本管理的数据。外部数据源是一个接口,用于在运行 terraform 的机器上本地运行命令,并提供该程序的控制台输出作为数据源。


这是一种允许本地脚本充当数据源的机制。要成为有效的数据源,本地脚本只需将 JSON 打印为标准输出,如下所示:


4.1 测试场景


使用 Terraform 编写编排文件,获取 github 个人资料信息。

4.2 代码


├── main.tf
├── outputs.tf
├── scripts
│ └── py
│ └── fetch_githubinfo.py
└── variables.tf
复制代码


  • main.tf


data "external" "githubinfo" {
program = ["python", "${path.module}/scripts/py/fetch_githubinfo.py"]
query = {
gitName = var.gitName
}
}
locals {
resp = data.external.githubinfo.result
}
复制代码


  • variables.tf


variable "gitName" {
type = string
}
复制代码


  • outputs.tf


output "resp" {
value = {
get = local.resp
}
}
复制代码


  • fetch_githubinfo.py


#!/usr/bin/env python3
# coding: utf-8
import json
from terraform_external_data import terraform_external_data
import requests
import json
@terraform_external_data
def fetch(query):
# Terraform requires the values you return be strings,
# so terraform_external_data will error if they aren't.
gitName = query['gitName']
response = requests.get(f'https://api.github.com/users/{gitName}')
output_json = response.json()
return {str(key): str(value) for key, value in output_json.items()}
if __name__ == "__main__":
fetch()
复制代码

4.3 测试


执行 terraform init/terraform apply


4.4 其他


  • terraform 扮演执行器,可以执行 shell/js/golang/python 等各语言代码,但需要在执行环境中具备对应语言的解释器。

五 总结


利用 data 的 http/external 可以非常方便的是心啊调用外部接口获取数据。但官方对于 External Data Source 的定位是"逃生窗口",因此在考虑使用该方案时,为最后手段。

参考链接



点击关注,第一时间了解华为云新鲜技术~

发布于: 刚刚阅读数: 3
用户头像

提供全面深入的云计算技术干货 2020-07-14 加入

生于云,长于云,让开发者成为决定性力量

评论

发布
暂无评论
带你掌握利用Terraform不同数据源扩展应用场景_开发_华为云开发者联盟_InfoQ写作社区