https://github.com/mashiike/hclconfig
utility go package for loading configuration files by HCL
https://github.com/mashiike/hclconfig
Last synced: 3 months ago
JSON representation
utility go package for loading configuration files by HCL
- Host: GitHub
- URL: https://github.com/mashiike/hclconfig
- Owner: mashiike
- License: mit
- Created: 2022-09-13T07:20:34.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2023-03-27T21:01:05.000Z (about 2 years ago)
- Last Synced: 2024-05-01T16:15:23.499Z (about 1 year ago)
- Language: Go
- Size: 77.1 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# hclconfig
[](https://godoc.org/github.com/mashiike/hclconfig)


[](https://goreportcard.com/report/mashiike/hclconfig)
[](https://github.com/mashiike/hclconfig/blob/master/LICENSE)go utility package for loading HCL(HashiCorp configuration language) files
-----
## Features
* Local Variables
* Implicit variables
* Built-in functions using standard libraries
* Interfaces to implement additional restrictions## Requirements
* Go 1.18 or higher. support the 3 latest versions of Go.See [godoc.org/github.com/mashiike/hclconfig](https://godoc.org/github.com/mashiike/hclconfig).
-----
## Installation
```shell
$ go get -u github.com/mashiike/hclconfig
```## Usage
config/config.hcl
```hcl
io_mode = "readonly"service "http" "hoge" {
addr = "http://127.0.0.1"
port = 8080
}
``````go
package mainimport (
"github.com/mashiike/hclconfig"
)type Config struct {
IOMode string `hcl:"io_mode"`
Services []ServiceConfig `hcl:"service,block"`
}type ServiceConfig struct {
Type string `hcl:"type,label"`
Name string `hcl:"name,label"`
Addr string `hcl:"addr"`
Port int `hcl:"port"`
}func main() {
var cfg Config
if err := hclconfig.Load(&cfg, "./config"); err != nil {
panic(err)
}
//...
}
```
### Local VariablesFor example, the following statements are possible
config/config.hcl
```hcl
locals {
addr = "http://127.0.0.1"
}
io_mode = "readonly"service "http" "hoge" {
addr = local.addr
port = 8080
}service "http" "fuga" {
addr = local.addr
port = 8081
}
```### Implicit variables
For example, the following statements are possible
config/config.hcl
```hcl
io_mode = "readonly"service "http" "hoge" {
addr = "http://127.0.0.1"
port = 8080
}service "http" "fuga" {
addr = "http://127.0.0.1"
port = service.http.hoge.port + 1
}
```This is the ability to refer to other blocks and attributes as implicit variables.
The evaluation of this implicit variable is done recursively. Up to 100 nests can be evaluated.### Built-in functions
You can use the same functions that you use most often.
For example, you can use the `must_env` or `env` functions to read environment variables. To read from a file, you can use the `file` function.
```hcl
env = must_env("ENV")
shell = env("SHELL", "bash")
text = file("memo.txt")
```You can also use other functions from "github.com/zclconf/go-cty/cty/function/stdlib" such as `jsonencode` and `join`.
### Additional restrictions
If the following interfaces are met, functions can be called after decoding to implement additional restrictions.
```go
type Restrictor interface {
Restrict(bodyContent *hcl.BodyContent, ctx *hcl.EvalContext) hcl.Diagnostics
}
```example code
```go
package mainimport (
"github.com/hashicorp/hcl/v2"
"github.com/mashiike/hclconfig"
)type Config struct {
IOMode string `hcl:"io_mode"`
Services []ServiceConfig `hcl:"service,block"`
}type ServiceConfig struct {
Type string `hcl:"type,label"`
Name string `hcl:"name,label"`
Addr string `hcl:"addr"`
Port int `hcl:"port"`
}func (cfg *Config) Restrict(content *hcl.BodyContent, ctx *hcl.EvalContext) hcl.Diagnostics {
var diags hcl.Diagnostics
if cfg.IOMode != "readwrite" && cfg.IOMode != "readonly" {
diags = append(diags, hclconfig.NewDiagnosticError(
"Invalid io_mode",
"Possible values for io_mode are readwrite or readonly",
hclconfig.AttributeRange(content, "io_mode"),
))
}
diags = append(diags, hclconfig.RestrictUniqueBlockLabels(content)...)
return diags
}func main() {
var cfg Config
if err := hclconfig.Load(&cfg, "./config"); err != nil {
panic(err)
}
//...
}
```In this case, if anything other than readonly and readwrite is entered in the IOMode, the following message is output.
```hcl
io_mode = "public"service "http" "hoge" {
addr = "http://127.0.0.1"
port = 8080
}service "http" "hoge" {
addr = "http://127.0.0.1"
port = 8080
}
``````
Error: Invalid io_modeon config/config.hcl line 1:
1: io_mode = "public"Possible values for io_mode are readwrite or readonly
Error: Duplicate service "http" configuration
on config/config.hcl line 8, in service "http" "hoge":
8: service "http" "hoge" {A http service named "hoge" was already declared at config/config.hcl:3,1-22. service names must unique per type in a configuration
```### Custom Decode
If the given Config satisfies the following interfaces, call the customized decoding process after calculating Local Variables and Implicit Variables
```go
type BodyDecoder interface {
DecodeBody(hcl.Body, *hcl.EvalContext) hcl.Diagnostics
}
```In this case, it should be noted that Restrictor does not work because all DecodeBody is replaced.
When using the BodyDecocder interface, additional restrictions, etc., should also be implemented in the DecodeBody function.## LICENSE
MIT