Skip to content

Instantly share code, notes, and snippets.

@kjanshair
Forked from mitchellh/parse.go
Created August 31, 2020 22:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kjanshair/618307061120444c58c0675ed66aa771 to your computer and use it in GitHub Desktop.
Save kjanshair/618307061120444c58c0675ed66aa771 to your computer and use it in GitHub Desktop.
HCL2 parsing example.
package config
import (
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"github.com/hashicorp/hcl2/gohcl"
"github.com/hashicorp/hcl2/hcl"
"github.com/hashicorp/hcl2/hcl/hclsyntax"
"github.com/hashicorp/hcl2/hcl/json"
)
// ParseFile parses the given file for a configuration. The syntax of the
// file is determined based on the filename extension: "hcl" for HCL,
// "json" for JSON, other is an error.
func ParseFile(filename string) (*Config, error) {
f, err := os.Open(filename)
if err != nil {
return nil, err
}
defer f.Close()
ext := filepath.Ext(filename)
if len(ext) > 0 {
ext = ext[1:]
}
return Parse(f, filename, ext)
}
// Parse parses the configuration from the given reader. The reader will be
// read to completion (EOF) before returning so ensure that the reader
// does not block forever.
//
// format is either "hcl" or "json"
func Parse(r io.Reader, filename, format string) (*Config, error) {
switch format {
case "hcl":
return parseHCL(r, filename)
case "json":
return parseJSON(r, filename)
default:
return nil, fmt.Errorf("Format must be either 'hcl' or 'json'")
}
}
func parseHCL(r io.Reader, filename string) (*Config, error) {
src, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}
f, diag := hclsyntax.ParseConfig(src, filename, hcl.Pos{})
if diag.HasErrors() {
return nil, diag
}
var config Config
diag = gohcl.DecodeBody(f.Body, nil, &config)
if diag.HasErrors() {
return nil, diag
}
return &config, nil
}
func parseJSON(r io.Reader, filename string) (*Config, error) {
src, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}
f, diag := json.Parse(src, filename)
if diag.HasErrors() {
return nil, diag
}
var config Config
diag = gohcl.DecodeBody(f.Body, nil, &config)
if diag.HasErrors() {
return nil, diag
}
return &config, nil
}
package config
import (
"os"
"path/filepath"
"testing"
"github.com/davecgh/go-spew/spew"
"github.com/sebdah/goldie"
"github.com/stretchr/testify/require"
)
func init() {
goldie.FixtureDir = "testdata"
spew.Config.DisablePointerAddresses = true
}
func TestParseFile(t *testing.T) {
f, err := os.Open("testdata")
require.NoError(t, err)
defer f.Close()
fis, err := f.Readdir(-1)
require.NoError(t, err)
for _, fi := range fis {
if fi.IsDir() {
continue
}
if filepath.Ext(fi.Name()) == ".golden" {
continue
}
t.Run(fi.Name(), func(t *testing.T) {
cfg, err := ParseFile(filepath.Join("testdata", fi.Name()))
require.NoError(t, err)
goldie.Assert(t, fi.Name(), []byte(spew.Sdump(cfg)))
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment