我的目标是解析一个HCL配置(),然后将收集到的有关变量、输出、资源块和数据块的数据写入Markdown文件。
但是,只要我试图解码具有多个标签的资源块,变量和输出就没有问题。
Works:
variable "foo" {
type = "bar"
}不工作:
resource "foo" "bar" {
name = "biz"
}错误:Extraneous label for resource; Only 1 labels (name) are expected for resource blocks.
类型声明代码:
import (
"log"
"os"
"strconv"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/gohcl"
"github.com/hashicorp/hcl/v2/hclsyntax"
)
type Variable struct {
Name string `hcl:",label"`
Description string `hcl:"description,optional"`
Sensitive bool `hcl:"sensitive,optional"`
Type *hcl.Attribute `hcl:"type,optional"`
Default *hcl.Attribute `hcl:"default,optional"`
Options hcl.Body `hcl:",remain"`
}
type Output struct {
Name string `hcl:",label"`
Description string `hcl:"description,optional"`
Sensitive bool `hcl:"sensitive,optional"`
Value string `hcl:"value,optional"`
Options hcl.Body `hcl:",remain"`
}
type Resource struct {
Name string `hcl:"name,label"`
Options hcl.Body `hcl:",remain"`
}
type Data struct {
Name string `hcl:"name,label"`
Options hcl.Body `hcl:",remain"`
}
type Config struct {
Outputs []*Output `hcl:"output,block"`
Variables []*Variable `hcl:"variable,block"`
Resources []*Resource `hcl:"resource,block"`
Data []*Data `hcl:"data,block"`
}解码码:
func createDocs(hclPath string) map[string][]map[string]string {
var variables, outputs []map[string]string
parsedConfig := make(map[string][]map[string]string)
hclConfig := make(map[string][]byte)
c := &Config{}
// Iterate all Terraform files and safe the contents in the hclConfig map
for _, file := range filesInDirectory(hclPath, ".tf") {
fileContent, err := os.ReadFile(hclPath + "/" + file.Name())
if err != nil {
log.Fatal(err)
}
hclConfig[file.Name()] = fileContent
}
// Iterate all file contents
for k, v := range hclConfig {
parsedConfig, diags := hclsyntax.ParseConfig(v, k, hcl.Pos{Line: 1, Column: 1})
if diags.HasErrors() {
log.Fatal(diags)
}
diags = gohcl.DecodeBody(parsedConfig.Body, nil, c)
if diags.HasErrors() {
log.Fatal(diags)
}
}
for _, v := range c.Variables {
var variableType string
var variableDefault string
if v.Type != nil {
variableType = (v.Type.Expr).Variables()[0].RootName()
}
if v.Default != nil {
variableDefault = (v.Default.Expr).Variables()[0].RootName()
}
variables = append(variables, map[string]string{"name": v.Name, "description": v.Description,
"sensitive": strconv.FormatBool(v.Sensitive), "type": variableType, "default": variableDefault})
}
for _, v := range c.Outputs {
outputs = append(outputs, map[string]string{"name": v.Name, "description": v.Description,
"sensitive": strconv.FormatBool(v.Sensitive), "value": v.Value})
}
parsedConfig["variables"], parsedConfig["outputs"] = variables, outputs
return parsedConfig
}问题:如何从资源块解析多个标签?
发布于 2022-05-11 23:48:29
您所共享的错误是由于type Resource的定义造成的。Terraform中的resource块(和data块)需要两个标签,指示资源类型和名称。为了在模式中与这些结构类型相匹配,您需要定义为标记为label的字段
type Resource struct {
Type string `hcl:"type,label"`
Name string `hcl:"name,label"`
Options hcl.Body `hcl:",remain"`
}
type Data struct {
Type string `hcl:"type,label"`
Name string `hcl:"name,label"`
Options hcl.Body `hcl:",remain"`
}虽然这应该适用于您在这里展示的有限的输入,但我想提醒您,您使用的是更高级别的gohcl API,它只能解码映射到Go结构类型的HCL的一个子集。Terraform本身直接使用hcl.Body和hcl.Expression的低级API,这允许Terraform语言包含gohcl API无法直接表示的一些gohcl特性。
根据您的目标,您可能会发现使用官方库terraform-config-inspect更好,它可以在比HCL本身更高的抽象级别上解析、解码和描述Terraform语言的子集。它还支持为Terraform版本编写的模块,可以追溯到Terraformv0.11,是支持Terraform注册表对模块进行分析的实现。
https://stackoverflow.com/questions/72197201
复制相似问题