hashicorp/hcl

GitHub: hashicorp/hcl

HCL 是 HashiCorp 开发的配置语言工具包,专为构建人类友好且机器可处理的结构化配置格式而设计,广泛应用于 DevOps 工具和基础设施即代码场景。

Stars: 5795 | Forks: 641

# HCL HCL 是一个用于创建结构化配置语言的工具包,这些配置语言既对人类友好,也易于机器处理,适用于命令行工具。虽然 HCL 旨在通用,但主要面向 DevOps 工具、服务器等场景。 HCL 既拥有一种*原生语法*(旨在让人类读起来和写起来都很愉悦),也提供了一种基于 JSON 的变体,这种变体更易于机器生成和解析。 HCL 原生语法的灵感来源于 [libucl](https://github.com/vstakhov/libucl)、[nginx configuration](http://nginx.org/en/docs/beginners_guide.html#conf_structure) 等。它包含一种表达式语法,允许进行基本的内联计算,并在调用应用程序的支持下,使用变量和函数来实现更具动态性的配置语言。 HCL 提供了一组构造,调用应用程序可以使用它们来构建配置语言。应用程序定义预期的属性名称和嵌套块类型,HCL 解析配置文件,验证其是否符合预期的结构,并返回高层对象供应用程序进一步处理。 ``` package main import ( "log" "github.com/hashicorp/hcl/v2/hclsimple" ) type Config struct { IOMode string `hcl:"io_mode"` Service ServiceConfig `hcl:"service,block"` } type ServiceConfig struct { Protocol string `hcl:"protocol,label"` Type string `hcl:"type,label"` ListenAddr string `hcl:"listen_addr"` Processes []ProcessConfig `hcl:"process,block"` } type ProcessConfig struct { Type string `hcl:"type,label"` Command []string `hcl:"command"` } func main() { var config Config err := hclsimple.DecodeFile("config.hcl", nil, &config) if err != nil { log.Fatalf("Failed to load configuration: %s", err) } log.Printf("Configuration is %#v", config) } ``` 对于需要对配置的解析、解码和评估进行更严格控制的应用程序,可以使用更低级别的 API。更多信息,请参阅 [the package documentation](https://pkg.go.dev/github.com/hashicorp/hcl/v2)。 ## 为什么选择 HCL? HCL 的新用户经常会问:为什么不使用 JSON、YAML 等? 虽然 JSON 和 YAML 是用于序列化数据结构的格式,但 HCL 是一种专门为构建结构化配置格式而设计的语法和 API。 HCL 试图在通用序列化格式(如 JSON)和围绕完整编程语言(如 Ruby)构建的配置格式之间寻求折中。HCL 语法的旨在易于人类读写,并允许*声明式*逻辑,以便在更复杂的应用程序中使用。 HCL 旨在作为一种配置格式的基础语法,这些格式围绕键值对和分层块构建,其结构由调用应用程序明确定义,而这种配置结构的定义允许提供更好的错误信息,并使调用应用程序内部的定义更加便捷。 不可否认,JSON 作为不同软件之间互操作的*通用语*非常方便。因此,HCL 定义了一个通用配置模型,既可以从其原生语法解析,也可以从定义明确的等效 JSON 结构解析。这允许配置以原生语法的人工编写配置文件和 JSON 的机器生成文件的混合形式提供。 ## 信息模型与语法 HCL 围绕两个主要概念构建:*属性*(attributes)和*块*(blocks)。在原生语法中,假设应用程序的配置文件可能如下所示: ``` io_mode = "async" service "http" "web_proxy" { listen_addr = "127.0.0.1:8080" process "main" { command = ["/usr/local/bin/awesome-app", "server"] } process "mgmt" { command = ["/usr/local/bin/awesome-app", "mgmt"] } } ``` 此配置的 JSON 等效形式如下: ``` { "io_mode": "async", "service": { "http": { "web_proxy": { "listen_addr": "127.0.0.1:8080", "process": { "main": { "command": ["/usr/local/bin/awesome-app", "server"] }, "mgmt": { "command": ["/usr/local/bin/awesome-app", "mgmt"] }, } } } } } ``` 无论使用哪种语法,调用应用程序内部的 API 都是相同的。对于更高级的用例,它可以直接处理低级别的属性和块,或者可以使用 _decoder_ 包之一将其声明式地提取到 Go 结构体或动态值结构中。 属性值可以是表达式,也可以是字面量值: ``` # 字面量与应用程序提供变量的算术运算 sum = 1 + addend # 字符串插值与模板 message = "Hello, ${name}!" # 应用程序提供的函数 shouty_message = upper(message) ``` 虽然 JSON 语法不允许直接使用表达式,但插值语法允许在 JSON 字符串中使用任意表达式: ``` { "sum": "${1 + addend}", "message": "Hello, ${name}!", "shouty_message": "${upper(message)}" } ``` 有关更多信息,请参阅详细规范: * [Syntax-agnostic Information Model](spec.md) * [HCL Native Syntax](hclsyntax/spec.md) * [JSON Representation](json/spec.md) ## 2.0 版本的变化 HCL 版本 2.0 结合了 HCL 1.0 的功能和插值语言 HIL 的功能,产生了一种支持任意表达式的单一配置语言。 这个新版本拥有全新的解析器和 Go API,没有直接的迁移路径。虽然语法相似,但该实现采取了一些截然不同的方法,以改进原始实现中存在的一些“粗糙边缘”,并允许更健壮的错误处理。 可以使用 Go 的 _semantic import versioning_ 机制将 HCL 1 和 HCL 2 导入同一个程序: ``` import ( hcl1 "github.com/hashicorp/hcl" hcl2 "github.com/hashicorp/hcl/v2" ) ``` ## 致谢 HCL 深受 [libucl](https://github.com/vstakhov/libucl) 的启发,后者由 [Vsevolod Stakhov](https://github.com/vstakhov) 编写。 HCL 和 HIL 起源于 [HashiCorp Terraform](https://terraform.io/),其各自的原始解析器由 [Mitchell Hashimoto](https://github.com/mitchellh) 编写。 原始 HCL 解析器由 [Fatih Arslan](https://github.com/fatih) 移植为纯 Go(从 yacc)。新原生语法解析器中与结构相关的部分建立在该工作之上。 原始 HIL 解析器由 [Martin Atkins](https://github.com/apparentlymart) 移植为纯 Go(从 yacc)。新原生语法解析器中与表达式相关的部分建立在该工作之上。 将原始 HCL 和 HIL 语言合并为这一单一新语言的 HCL 2,建立在 [Martin Atkins](https://github.com/apparentlymart) 在 [zcl](https://github.com/zclconf/go-zcl) 中的设计和原型工作之上。
标签:EC2, ECS, EVTX分析, EVTX分析, Go语言, HashiCorp, HCL, IaC, JSON, Terraform, 人机交互友好, 开发工具包, 日志审计, 机器可读, 程序破解, 结构化数据, 网络调试, 自动化, 解析器, 配置语言