问题描述
从 Terraform 进行 REST API 调用的最佳方式是什么?我目前正在使用 null_resource
和 local-exec
供应商来进行 cURL 调用:
What is the best way to make REST API calls from Terraform? I'm currently using a null_resource
with the local-exec
provisioner to make a cURL call:
resource "null_resource" "cloudability-setup" {
provisioner "local-exec" {
command = <<EOT
curl -s -X POST https://api.cloudability.com/v3/vendors/aws/accounts
-H 'Content-Type: application/json'
-u "$${CldAbltyAPIToken:?Missing Cloudability API Token Env Variable}:"
-d '{"vendorAccountId": "${data.aws_caller_identity.current.account_id}", "type": "aws_role" }'
EOT
}
但是,对于 HTTP 200 和 HTTP 400 响应,cURL 返回码是成功的.如果无法注册新帐户,我希望将资源标记为失败.
However, the cURL return code is successful for HTTP 200 and HTTP 400 responses. I'd like the resource to be marked as failed if the new account cannot be registered.
我尝试只返回 HTTP 响应代码:
I've tried returning just the HTTP Response Code:
resource "null_resource" "cloudability-setup" {
provisioner "local-exec" {
command = <<EOT
curl -s -o /dev/null -w "%{http_code}"
-X POST https://api.cloudability.com/v3/vendors/aws/accounts
-H 'Content-Type: application/json'
-u "$${CldAbltyAPIToken:?Missing Cloudability API Token Env Variable}:"
-d '{"vendorAccountId": "${data.aws_caller_identity.current.account_id}", "type": "aws_role" }'
EOT
}
但随后我丢失了 API 响应正文,其中包含有价值的信息.有时 HTTP 400 代码表明该帐户已经存在,从整体设置的角度来看,我认为这是成功的.
But then I lose the API response body, which contains valuable information. There are also times when a HTTP 400 code indicates the account already exists, which I consider a success from the overall setup standpoint.
推荐答案
这个问题已经被浏览了超过 10,000 次,我意识到我从来没有发布我的解决方案.我最终编写了一个 Python 脚本来处理各种 API 响应并控制对 Terraform 的返回代码.
This question has been viewed over 10,000 times and I realized I never posted my solution to the problem. I ended up writing a Python script to handle the various API responses and controlling the return codes to Terraform.
地形资源:
resource "null_resource" "cloudability-setup" {
provisioner "local-exec" {
command = "${path.module}/cloudability_setup.py -a ${data.aws_caller_identity.current.account_id} -t aws_role"
}
depends_on = ["aws_iam_role.cloudability-role"]
}
Python 脚本:
import getopt
import json
import os
import requests
import sys
def print_help():
print '''
Usage: cloudability_setup.py [options]
cloudability_setup -- Register new account with Cloudability
Options:
-h, --help Show this help message and exit
-a <acct #>, --acctnum=<acct #>
Required argument: IaaS Account Number
-t <type>, --type=<type>
Required argument: IaaS Account Type
'''
def register_acct(acctnum, type):
url = 'https://api.cloudability.com/v3/vendors/aws/accounts'
token = os.environ['CldAbltyAPIToken']
headers = {'Content-Type': 'application/json'}
data = '{"vendorAccountId": "' + acctnum + '", "type": "'+ type + '" }'
response = requests.post(url, auth=(token,''), headers=headers, data=data)
# If new account was registered successfully, update externalID:
if response.status_code == requests.codes.created:
update_acct(acctnum, type)
# If account already exists, update externalID:
elif str(response.status_code) == '409':
update_acct(acctnum, type)
else:
print "Bad response from Cloudability API while registering new account."
print "HTTP: " + str(response.status_code)
sys.exit(3)
def update_acct(acctnum, type):
url = 'https://api.cloudability.com/v3/vendors/aws/accounts/' + acctnum
token = os.environ['CldAbltyAPIToken']
headers = {'Content-Type': 'application/json'}
data = '{"type": "' + type + '", "externalId": "XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX" }'
response = requests.put(url, auth=(token,''), headers=headers, data=data)
if response.status_code == requests.codes.ok:
sys.exit()
else:
print "Bad response from Cloudability API while updating account."
print "HTTP: " + str(response.status_code)
sys.exit(3)
def main(argv=None):
'''
Main function: work with command line options and send an HTTPS request to the Cloudability API.
'''
try:
opts, args = getopt.getopt(sys.argv[1:], 'ha:t:',
['help', 'acctnum=', 'type='])
except getopt.GetoptError, err:
# Print help information and exit:
print str(err)
print_help()
sys.exit(2)
# Initialize parameters
acctnum = None
type = None
# Parse command line options
for opt, arg in opts:
if opt in ('-h', '--help'):
print_help()
sys.exit()
elif opt in ('-a', '--acctnum'):
acctnum = arg
elif opt in ('-t', '--type'):
type = arg
# Enforce required arguments
if not acctnum or not type:
print_help()
sys.exit(4)
register_acct(acctnum, type)
if __name__ == '__main__':
sys.exit(main())
这篇关于使用 cURL 调用 Terraform REST API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!