本文分享自华为云社区《利用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的定位是"逃生窗口",因此在考虑使用该方案时,为最后手段。

参考链接

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

带你掌握利用Terraform不同数据源扩展应用场景的更多相关文章

  1. WPF 自带Datagrid编辑后无法更新数据源的问题

    原文  WPF 自带Datagrid编辑后无法更新数据源的问题 解决办法: 在列的绑定属性里加上UpdateSourceTrigger,示例XAML如下 <DataGrid Grid.Row=& ...

  2. Azure Terraform(十二)利用 Terraform 将文件上传到 Azure Blob Storage

    一,引言 本篇文章中,我门将学习如何利用 Terraform 将 文件以及文件夹上传到 Azure Blob Storage,这个对于我们来说很方便,可以将一些不重要的内容也存储在源代码管理工具中! ...

  3. 理解钩子Hook以及在Thinkphp下利用钩子使用行为扩展

    什么是钩子函数 个人理解:钩子就像一个”陷阱”.”监听器”,当A发送一个消息到B时,当消息还未到达目的地B时,被钩子拦截调出一部分代码做处理,这部分代码也叫钩子函数或者回调函数 参考网上说法 譬如我们 ...

  4. 利用Delphi编写IE扩展

    就是如何使IE扩展组件可以响应事件.    在自己的程序中使用过WebBrowser控件的朋友都知道,WebBrowser控件定义了诸如BeforeNavigate.DownloadComplete ...

  5. 一分钟带你学会利用mybatis-generator自动生成代码!

    目录 一.MyBatis Generator简介 二.使用方式 三.实战 之前的文章<SpringBoot系列-整合Mybatis(XML配置方式)>介绍了XML配置方式整合的过程,本文介 ...

  6. java分享第十八天-02( java结合testng,利用XML做数据源的数据驱动)

    testng的功能很强大,利用@DataProvider可以做数据驱动,数据源文件可以是EXCEL,XML,YAML,甚至可以是TXT文本.在这以XML为例:备注:@DataProvider的返回值类 ...

  7. 利用phpize 外挂php扩展

    如果你的php是手动编译安装的 ,可能有一些扩展一开始并没有开启,以后需要某扩展的时候又不想重新编译php,使用phpize可以动态添加扩展 以Ubuntu为例, 如果你是我这样安装php的  apt ...

  8. C# 利用范型与扩展方法重构代码

    在一些C#代码中常常可以看到 //An Simple Example By Ray Linn class CarCollection :ICollection { IList list; public ...

  9. java结合testng,利用excel做数据源的数据驱动实例

    数据驱动部分,是自动化测试常用部分,也是参数化设计的重要环节,前面分享了,mysql.yaml做数据源,那么再来分享下excel做数据驱动 思路: 先用POI读取excel.解析读取数据,返回list ...

  10. java结合testng,利用yaml做数据源的数据驱动实例

    testng的功能很强大,利用@DataProvider可以做数据驱动,数据源文件可以是EXCEL,XML,YAML,甚至可以是TXT文本.在这以yaml为例: 备注:@DataProvider的返回 ...

随机推荐

  1. Network Science: 巴拉巴西网络科学阅读笔记

    前言: 最小生成树中Kruskal算法对应了统计物理中的著名模型invasion percolation.由此写了一篇文章:invasion percolation and global optimi ...

  2. Go中的有限状态机FSM的详细介绍

    1.FSM简介 1.1 有限状态机的定义 有限状态机(Finite State Machine,FSM)是一种数学模型,用于描述系统在不同状态下的行为和转移条件. 状态机有三个组成部分:状态(Stat ...

  3. chrome Dev Tools 性能分析 performance

    chrome 的performance用来分析性能优化性能非常好用,下面以一个页面来举例 性能分析 性能分析最好使用隐私无痕模式,以保证干净的环境下,避免chrome插件对性能分析结果的影响 Perf ...

  4. js 获取窗口/容器内部滚动位置

    前端 (document.getElementsByClassName("container")[0]).scrollTop -- 容器内部滚动条位置 (document.getE ...

  5. 2022CSP游记

    目录 CSP-J2022 7:45 8:15 8:27 8:38 9:12 9:23 10:34 11:57 中午 CSP-S2022 2:27 4:15 6:12 估分 普及 提高 自查 出分 废物 ...

  6. NUXT3.0实现网络请求二次封装

    最近在开发基于nuxt3.0的项目,看了官网的网络请求,感觉不太适合,就自己基于官网的useFetch()方法封装了一个网络请求,下面开始实现封装. 第一步:新建http.ts文件,用于编写封装代码 ...

  7. 卧槽Winform也可以这么好看?

    Winform也可以这么好看? 对于Winform很多人的刻板印象就是拖拉拽,简单生产界面,但是这样对于界面的效果,它并不会很好,虽然简单,快,但是效果也是极差,所以有很多人就去使用WPF,去写xml ...

  8. JSP课设之项目管理

    一.准备: JDK1.8,eclipse,Tomcat(Web服务器),JDBC驱动(链接数据库) java+html+css+jsp+javabean+DAO+servlet 二.步骤: 1.装JD ...

  9. 2022-08-12:方案1 : {7, 10}; xxxx : {a , b}; 1 2 3 4; FunnyGoal = 100; OffenseGoal = 130。 找到一个最少方案数,让Fu

    2022-08-12:方案1 : {7, 10}: xxxx : {a , b}: 1 2 3 4: FunnyGoal = 100: OffenseGoal = 130. 找到一个最少方案数,让Fu ...

  10. 2021-07-18:最高的广告牌。你正在安装一个广告牌,并希望它高度最大。这块广告牌将有两个钢制支架,两边各一个。每个钢支架的高度必须相等。你有一堆可以焊接在一起的钢筋 rods。举个例子,如果钢筋

    2021-07-18:最高的广告牌.你正在安装一个广告牌,并希望它高度最大.这块广告牌将有两个钢制支架,两边各一个.每个钢支架的高度必须相等.你有一堆可以焊接在一起的钢筋 rods.举个例子,如果钢筋 ...