利用Terraform不同数据源扩展应用场景

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

一 背景

在生产环境中使用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
data "external" "githubinfo" {

  program = ["python", "${path.module}/scripts/py/fetch_githubinfo.py"]
  query = {
    gitName = var.gitName
  }
}

locals {
  resp = data.external.githubinfo.result
}
variable "gitName" {
  type = string
}
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的定位是"逃生窗口",因此在考虑使用该方案时,为最后手段。

参考链接

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。