go - 无法将 terraform variables.tf 文件读入 may go 程序
问题描述
我正在尝试编写一个读取 terraformvariables.tf
并填充结构以供以后操作的 go 程序。但是,尝试“解析”文件时出现错误。我希望有人能告诉我我做错了什么:
代码:
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/gohcl"
"github.com/hashicorp/hcl/v2/hclsyntax"
)
type Config struct {
Upstreams []*TfVariable `hcl:"variable,block"`
}
type TfVariable struct {
Name string `hcl:",label"`
// Default string `hcl:"default,optional"`
Type string `hcl:"type"`
Description string `hcl:"description,attr"`
// validation block
Sensitive bool `hcl:"sensitive,optional"`
}
func main() {
readHCLFile("examples/string.tf")
}
// Exits program by sending error message to standard error and specified error code.
func abort(errorMessage string, exitcode int) {
fmt.Fprintln(os.Stderr, errorMessage)
os.Exit(exitcode)
}
func readHCLFile(filePath string) {
content, err := ioutil.ReadFile(filePath)
if err != nil {
log.Fatal(err)
}
fmt.Printf("File contents: %s", content) // TODO: Remove me
file, diags := hclsyntax.ParseConfig(content, filePath, hcl.Pos{Line: 1, Column: 1})
if diags.HasErrors() {
log.Fatal(fmt.Errorf("ParseConfig: %w", diags))
}
c := &Config{}
diags = gohcl.DecodeBody(file.Body, nil, c)
if diags.HasErrors() {
log.Fatal(fmt.Errorf("DecodeBody: %w", diags))
}
fmt.Println(c) // TODO: Remove me
}
错误
File contents: variable "image_id" {
type = string
description = "The id of the machine image (AMI) to use for the server."
sensitive = false
}
variable "other_id" {
type = string
description = "The id of the machine image (AMI) to use for the server."
sensitive = true
}
2021/03/13 19:55:49 DecodeBody: examples/string.tf:2,17-23: Variables not allowed; Variables may not be used here., and 3 other diagnostic(s)
exit status 1
堆栈驱动程序问题可悲的是 hcl1
我正在参考的博客文章。
解决方案
看起来它是库的错误/功能,因为一旦您更改string
为"string"
,例如,
variable "image_id" {
type = string
...
至
variable "image_id" {
type = "string"
...
gohcl.DecodeBody
成功。
- - 更新 - -
所以,他们确实在 Terraform 中使用了这个包,但是他们自定义解析配置,即他们不使用gohcl.DecodeBody
. 他们还通过使用(比较)来自定义处理 属性。正如您所假设的,它们确实使用了自定义类型for ,但使用自定义解析您不必这样做。type
hcl.ExprAsKeyword
description
type
下面是一个工作示例:
package main
import (
"fmt"
"log"
"os"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/gohcl"
"github.com/hashicorp/hcl/v2/hclsyntax"
)
var (
configFileSchema = &hcl.BodySchema{
Blocks: []hcl.BlockHeaderSchema{
{
Type: "variable",
LabelNames: []string{"name"},
},
},
}
variableBlockSchema = &hcl.BodySchema{
Attributes: []hcl.AttributeSchema{
{
Name: "description",
},
{
Name: "type",
},
{
Name: "sensitive",
},
},
}
)
type Config struct {
Variables []*Variable
}
type Variable struct {
Name string
Description string
Type string
Sensitive bool
}
func main() {
config := configFromFile("examples/string.tf")
for _, v := range config.Variables {
fmt.Printf("%+v\n", v)
}
}
func configFromFile(filePath string) *Config {
content, err := os.ReadFile(filePath) // go 1.16
if err != nil {
log.Fatal(err)
}
file, diags := hclsyntax.ParseConfig(content, filePath, hcl.Pos{Line: 1, Column: 1})
if diags.HasErrors() {
log.Fatal("ParseConfig", diags)
}
bodyCont, diags := file.Body.Content(configFileSchema)
if diags.HasErrors() {
log.Fatal("file content", diags)
}
res := &Config{}
for _, block := range bodyCont.Blocks {
v := &Variable{
Name: block.Labels[0],
}
blockCont, diags := block.Body.Content(variableBlockSchema)
if diags.HasErrors() {
log.Fatal("block content", diags)
}
if attr, exists := blockCont.Attributes["description"]; exists {
diags := gohcl.DecodeExpression(attr.Expr, nil, &v.Description)
if diags.HasErrors() {
log.Fatal("description attr", diags)
}
}
if attr, exists := blockCont.Attributes["sensitive"]; exists {
diags := gohcl.DecodeExpression(attr.Expr, nil, &v.Sensitive)
if diags.HasErrors() {
log.Fatal("sensitive attr", diags)
}
}
if attr, exists := blockCont.Attributes["type"]; exists {
v.Type = hcl.ExprAsKeyword(attr.Expr)
if v.Type == "" {
log.Fatal("type attr", "invalid value")
}
}
res.Variables = append(res.Variables, v)
}
return res
}
为了完整起见,添加example/string.tf
:
variable "image_id" {
type = string
description = "The id of the machine image (AMI) to use for the server."
sensitive = false
}
variable "other_id" {
type = string
description = "The id of the machine image (AMI) to use for the server."
sensitive = true
}
推荐阅读
- matlab - 在 Matlab 中从图像中提取周期性图案
- html - 当我将鼠标悬停在标签上时如何消除延迟
- android - Android 将 mp3 歌曲从 listview 播放到另一个活动
- python - 无法使用 pipenv 创建虚拟环境
- windows - 如何从 Windows 机器上正确删除/卸载证书?只有 .dev 域有问题
- javascript - Angular 6 - 路由未发生 - 垫表行
- c - 这两种 volatile 限定符的用法都是多余的吗?
- log4j - 在 Wildfly 服务器参数中提供 catalina.home 值
- python - 如何使用枚举将文件的特定行读取到python中的变量?
- javascript - 为什么在渲染中返回之前将状态值添加到变量