我正在编写一种基于hdl的配置语言,其中某些类型的块可以使用表达式引用其他块,如下所示:
source "my_source" {
// some blocks and attributes...
to = destination.my_kafka_topic
}
destination "kafka" "my_kafka_topic" {
// some blocks and attributes...
}
destination "elasticsearch" "my_es_index" {
// some blocks and attributes...
}
(目标是为消息传递系统中的事件流建模,然后根据基础设施实现实际系统。)
在解析过程中,我只是对静态属性和块执行部分解码,并确保"hcl.Attribute
s可以解释为hcl.Traversal
s,但不求值(然而)。
type Source struct {
Name string // first HCL tag
/* ... */
To hcl.Traversal
}
type Destination struct {
Type string // first HCL tag
Name string // second HCL tag
/* ... */
}
之后,可引用块(如上面示例中的destination
)根据其Type
标签与某种Go类型关联,并且该Go类型始终实现称为Referenceable
的接口。
type Referenceable interface {
AsReference() *Destination
}
type Destination struct {
// fields that represent the destination in terms of address, protocol, etc.
}
在那个阶段,我知道如何构建一个参考表map[string]Referenceable
的映射,其中关键是<block_type>.<block_name>
(例如"destination.my_kafka_topic"
),但我不确定如何在hcl.EvalContext
中利用它来评估变量去Referenceable
s。
我想知道的是:如何在hcl.EvalContext
使用的cty
类型系统中表达Go接口?这可能吗?如果没有,是否建议在hcl.EvalContext
中注入*Destination
的实例?
我有几次试图在HCL中评估变量,总是碰壁。对于这样简单的事情来说,它们的API似乎过于复杂了:在配置文件的顶部定义变量,并在参考资料部分中引用它们。
我最终制作了我自己的格式,BCL,具有非常相似的语法。毕竟,我需要的是我喜欢的语法,而不是与HCL的100%兼容性(这实际上也是不同的-有Terraform HCL, Packer HCL和其他几个-每个依赖于HCL的应用程序使用不同)。
所以我没有直接解决你的hcl.EvalContext
问题,但我想为你提供至少一个不同的背景(双关语)-看看我的BCL项目。没有什么值得期待的东西,但是它很方便,经过了良好的测试,有一个很好的(和正确的!)生成的解析器和反序列化到Go结构。