Parse HCL keys in command config
This commit is contained in:
parent
f916ed349d
commit
b817b60183
|
@ -5,7 +5,9 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-multierror"
|
||||||
"github.com/hashicorp/hcl"
|
"github.com/hashicorp/hcl"
|
||||||
|
"github.com/hashicorp/hcl/hcl/ast"
|
||||||
"github.com/mitchellh/go-homedir"
|
"github.com/mitchellh/go-homedir"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -44,22 +46,65 @@ func LoadConfig(path string) (*Config, error) {
|
||||||
return nil, fmt.Errorf("Error expanding config path: %s", err)
|
return nil, fmt.Errorf("Error expanding config path: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var config Config
|
|
||||||
contents, err := ioutil.ReadFile(path)
|
contents, err := ioutil.ReadFile(path)
|
||||||
if !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return nil, err
|
}
|
||||||
}
|
|
||||||
|
|
||||||
obj, err := hcl.Parse(string(contents))
|
return ParseConfig(string(contents))
|
||||||
if err != nil {
|
}
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := hcl.DecodeObject(&config, obj); err != nil {
|
// ParseConfig parses the given configuration as a string.
|
||||||
return nil, err
|
func ParseConfig(contents string) (*Config, error) {
|
||||||
|
root, err := hcl.Parse(contents)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Top-level item should be the object list
|
||||||
|
list, ok := root.Node.(*ast.ObjectList)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("Failed to parse config: does not contain a root object")
|
||||||
|
}
|
||||||
|
|
||||||
|
valid := []string{
|
||||||
|
"token_helper",
|
||||||
|
}
|
||||||
|
if err := checkHCLKeys(list, valid); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var c Config
|
||||||
|
if err := hcl.DecodeObject(&c, list); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkHCLKeys(node ast.Node, valid []string) error {
|
||||||
|
var list *ast.ObjectList
|
||||||
|
switch n := node.(type) {
|
||||||
|
case *ast.ObjectList:
|
||||||
|
list = n
|
||||||
|
case *ast.ObjectType:
|
||||||
|
list = n.List
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("cannot check HCL keys of type %T", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
validMap := make(map[string]struct{}, len(valid))
|
||||||
|
for _, v := range valid {
|
||||||
|
validMap[v] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var result error
|
||||||
|
for _, item := range list.Items {
|
||||||
|
key := item.Keys[0].Token.Value().(string)
|
||||||
|
if _, ok := validMap[key]; !ok {
|
||||||
|
result = multierror.Append(result, fmt.Errorf(
|
||||||
|
"invalid key '%s' on line %d", key, item.Assign.Line))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &config, nil
|
return result
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package command
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -19,3 +20,28 @@ func TestLoadConfig(t *testing.T) {
|
||||||
t.Fatalf("bad: %#v", config)
|
t.Fatalf("bad: %#v", config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLoadConfig_noExist(t *testing.T) {
|
||||||
|
config, err := LoadConfig("nope/not-once/.never")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.TokenHelper != "" {
|
||||||
|
t.Errorf("expected %q to be %q", config.TokenHelper, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseConfig_badKeys(t *testing.T) {
|
||||||
|
_, err := ParseConfig(`
|
||||||
|
token_helper = "/token"
|
||||||
|
nope = "true"
|
||||||
|
`)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(err.Error(), "invalid key 'nope' on line 3") {
|
||||||
|
t.Errorf("bad error: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue