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, 人机交互友好, 开发工具包, 日志审计, 机器可读, 程序破解, 结构化数据, 网络调试, 自动化, 解析器, 配置语言