rodaine / hclencoder

HCL Encoder/Marshaller - Convert Go Types into HCL files

Home Page:https://godoc.org/github.com/rodaine/hclencoder

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Getting an error when encoding

mike182uk opened this issue · comments

Hey @rodaine,

Nice work on this! I was trying to use it for something, but things aren't quite working as expected.

Given the following example:

package main

import (
	"fmt"
	"github.com/hashicorp/hcl"
	"github.com/rodaine/hclencoder"
)

func main(){
	var config = `
foo = "bar"
bar = "baz"

qux {
	a = 1
	b = 2
}`

	var m = make(map[string]interface{})

	// decode HCL string

	obj, err := hcl.Parse(config)
	if err != nil {
		panic(err)
	}

	if err = hcl.DecodeObject(&m, obj); err != nil {
		panic(err)
	}

	fmt.Println(m)

	// encode HCL string

	enc, err := hclencoder.Encode(m)

	if err != nil {
		panic(err)
	}

	fmt.Println(string(enc))
}

I would of expected to get the encoded config back at the end. Instead I am getting an error:

panic: runtime error: index out of range

goroutine 1 [running]:
panic(0xf2ee0, 0xc42000a140)
        /usr/local/Cellar/go/1.7.3/libexec/src/runtime/panic.go:500 +0x1a1
github.com/hashicorp/hcl/hcl/printer.(*printer).objectItem(0xc42009e0e0, 0xc4200a68a0, 0x0, 0x0, 0x0)
        /Users/mike/.go/src/github.com/hashicorp/hcl/hcl/printer/nodes.go:222 +0x571
github.com/hashicorp/hcl/hcl/printer.(*printer).output(0xc42009e0e0, 0xf33a0, 0xc4200a68a0, 0x0, 0x0, 0x0)
        /Users/mike/.go/src/github.com/hashicorp/hcl/hcl/printer/nodes.go:182 +0xc3b
github.com/hashicorp/hcl/hcl/printer.(*printer).output(0xc42009e0e0, 0xfe800, 0xc4200a21a0, 0x0, 0x0, 0x0)
        /Users/mike/.go/src/github.com/hashicorp/hcl/hcl/printer/nodes.go:172 +0x562
github.com/hashicorp/hcl/hcl/printer.(*printer).objectItem(0xc42009e0e0, 0xc4200a6900, 0x0, 0x0, 0x0)
        /Users/mike/.go/src/github.com/hashicorp/hcl/hcl/printer/nodes.go:243 +0x2f5
github.com/hashicorp/hcl/hcl/printer.(*printer).output(0xc42009e0e0, 0xf33a0, 0xc4200a6900, 0x0, 0x0, 0x0)
        /Users/mike/.go/src/github.com/hashicorp/hcl/hcl/printer/nodes.go:182 +0xc3b
github.com/hashicorp/hcl/hcl/printer.(*printer).output(0xc42009e0e0, 0xfe800, 0xc4200a2220, 0x0, 0x0, 0x0)
        /Users/mike/.go/src/github.com/hashicorp/hcl/hcl/printer/nodes.go:172 +0x562
github.com/hashicorp/hcl/hcl/printer.(*printer).output(0xc42009e0e0, 0xf32a0, 0xc4200822d0, 0x0, 0x0, 0x0)
        /Users/mike/.go/src/github.com/hashicorp/hcl/hcl/printer/nodes.go:116 +0xe97
github.com/hashicorp/hcl/hcl/printer.(*Config).Fprint(0x1850d8, 0x186280, 0xc42009e070, 0x186740, 0xc4200822d0, 0xf2701, 0xc42009e070)
        /Users/mike/.go/src/github.com/hashicorp/hcl/hcl/printer/printer.go:32 +0x1a7
github.com/hashicorp/hcl/hcl/printer.Fprint(0x186280, 0xc42009e070, 0x186740, 0xc4200822d0, 0x0, 0x1)
        /Users/mike/.go/src/github.com/hashicorp/hcl/hcl/printer/printer.go:48 +0x55
github.com/rodaine/hclencoder.Encode(0xf2720, 0xc420082150, 0x1, 0x28, 0x0, 0x0, 0x0)
        /Users/mike/.go/src/github.com/rodaine/hclencoder/hclencoder.go:31 +0x210
main.main()

I noticed that if i set up the config map manually like:

map[string]interface{}{
	"foo": 1,
	"bar": "baz",
	"qux": map[string]interface{}{
		"a": 1,
		"b": 2,
	},
}

That it would work as expected an give me back the encoded output:

bar = "baz"

foo = 1

qux {
  a = 1
  b = 2
}

There seems to be a discrepancy with how the HCL is decoded then encoded.

Im not sure if its down to how i'm using it, or if something is a miss somewhere else. Any ideas?

Thanks

Looking into this a bit, it appears there's a discrepancy with how the HCL is decoded into the map compared to what the encoder/printer expects.

If you runfmt.Printf("%+v", m) against your code, you will see that the value for qux is not a map but a slice of maps with the one element. This behavior is expected, given that you could have multiple qux in your HCL file legally.

Working on a solution to get the AST generated by the encoder to match the AST from the parser.

For now you may be able to get the result you expect prior to a patch if you write qux = { instead of qux {

Having the same problem here but the struct is given (ie. cannot influence the source HCL). Did you make any progress on fixing this? If not, any further pointer on what could be done about this?

I took a stab at it around the time of the original issue, but unfortunately was unable to reach a solution. From what I can remember, there's a determinism problem with the AST that I wasn't able to work out.

@mike182uk try again with #11 being merged. I think it should fix your issue.

Verified that this now runs successfully for the testcase above. Feel free to open the ticket if you encounter any other issues, @mike182uk!