我有一个由“外部数据源”调用的Python程序,在这里解释如下:
https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source
代码看起来如下所示:
data "external" "example" {
program = ["python", "${path.module}/example-data-source.py"]
query = {
# arbitrary map from strings to strings, passed
# to the external program as the data query.
id = "abc123"
}
}我的外部Python程序是否有技术或解决办法来知道哪个terraform操作(计划、应用或销毁)正在调用外部数据?
是否有任何方法可以让hcl代码找到它正在被调用的操作?
更新#1
我知道我们可以传递参数作为查询参数。
问题是,Terraform脚本是否知道它被调用的是哪种Terraform操作类型?这样,我就可以在terraform变量中进行操作(应用/销毁),然后将其作为查询参数传递给Python程序?
发布于 2021-08-31 21:56:57
external data source无法推断Terraform操作类型是什么,因为它只在query argument中发送数据,如数据源文档中所提到和显示的那样。
例如,如果我们查看文档中的示例:
#!/bin/bash
# Exit if any of the intermediate steps fail
set -e
# Extract "foo" and "baz" arguments from the input into
# FOO and BAZ shell variables.
# jq will ensure that the values are properly quoted
# and escaped for consumption by the shell.
eval "$(jq -r '@sh "FOO=\(.foo) BAZ=\(.baz)"')"
# Placeholder for whatever data-fetching logic your script implements
FOOBAZ="$FOO $BAZ"
# Safely produce a JSON object containing the result value.
# jq will ensure that the value is properly quoted
# and escaped to produce a valid JSON string.
jq -n --arg foobaz "$FOOBAZ" '{"foobaz":$foobaz}'我们可以看到,它从通过stdin发送到程序的任何内容中读取foo和baz键。
如果我们以最简单的方式运行它,我们可以看到它如我们所期望的那样:
data "external" "example" {
program = ["sh", "${path.module}/example-data-source.sh"]
query = {
foo = "abc1234"
baz = "123abc"
}
}
output "example" {
value = data.external.example
}给出以下输出:
Outputs:
example = {
"id" = "-"
"program" = tolist([
"sh",
"./example-data-source.sh",
])
"query" = tomap({
"baz" = "123abc"
"foo" = "abc1234"
})
"result" = tomap({
"foobaz" = "abc1234 123abc"
})
"working_dir" = tostring(null)
}为了检查Terraform在stdin上的通信没有什么可疑之处,我们可以修改脚本,以便将传递到stdin上的内容登录到文件中(请注意,这将破坏示例脚本,使jq不再看到来自Terraform的输入):
#!/bin/bash
# Exit if any of the intermediate steps fail
set -e
# Log stdin inputs to an output file so we only output the formatted
# JSON on stdout for the external data source to work correctly.
cat - >> log.out
# Extract "foo" and "baz" arguments from the input into
# FOO and BAZ shell variables.
# jq will ensure that the values are properly quoted
# and escaped for consumption by the shell.
eval "$(jq -r '@sh "FOO=\(.foo) BAZ=\(.baz)"')"
# Placeholder for whatever data-fetching logic your script implements
FOOBAZ="$FOO $BAZ"
# Safely produce a JSON object containing the result value.
# jq will ensure that the value is properly quoted
# and escaped to produce a valid JSON string.
jq -n --arg foobaz "$FOOBAZ" '{"foobaz":$foobaz}'然后,如果我们运行一个计划,我们就可以在log.out文件中看到预期的JSON:
{"baz":"123abc","foo":"abc1234"}如果您可以在Terraform代码中访问操作类型,那么您可以将其作为参数传递给外部数据源,但不幸的是,也没有公开任何您可以访问的操作类型。
还值得一提的是,作为数据源,运行脚本可能会产生副作用。这意味着,在调用数据源时,Terraform运行的操作并不重要。如果您需要做一些没有副作用的事情,那么您可能需要考虑另一个选项,比如provisioner,它可能附加到null_resource上,但所有这些选项都是您需要一个逃生口的最后一个避风港。在大多数情况下,最好是在适当的提供者中提出一个特性请求,或者单独调用这些东西,并通过一个包装脚本或一些连续调用它们的编排软件将它们编排在一起。
发布于 2022-11-23 17:41:02
还没有对此进行测试,但是您应该可以使用os.getppid()获得terraform的pid。然后,您可以使用psutil (可在pip中获得)、/proc (仅限于linux)或子处理ps命令获得更多信息。在命令行中查找动词可能很脆弱,但取决于上下文,它可能会起作用。
尽管如此,如果您需要这样做,您应该重新考虑您的代码是如何组织的。纯粹的数据源不应该在意。
https://stackoverflow.com/questions/69004621
复制相似问题