Search code examples
goterraformterraform-provider

Parse HCL block into Golang map


I am implementing acceptance tests for a terraform provider, and I would like to use the same input variable to write my test plan and to assert that my resource is properly setup.

For my usecase I need to use TestCheckTypeSetElemNestedAttrs from Terraform Plugin SDK that expects a map[string]string.

How can I use the same variable to generate a Terraform block and a map[string]string easily (preferably without having to define structs).

I am looking for something like that :

func TestAccResource(t *testing.T) {
    t.Parallel()
    pr := TestAccProtoV6ProviderFactories

    name := "the name"

    innerBlock := `{
        field1 = 0
        field2 = false
        field4 = "value"
    }`

    innerBlockMap map[string]string := <------------ How to parse innerBlock to a map[string]string here ? 

    resource.Test(t, resource.TestCase{
        ProtoV6ProviderFactories: pr,
        Steps: []resource.TestStep{
            {
                Config: fmt.Sprintf(`
                resource "myprovider_myresource" "test" {
                    name = %[1]q
                    innerField = %[1]s
                }`, innerBlock, name),
                Check: resource.ComposeAggregateTestCheckFunc(
                    resource.TestCheckResourceAttr("myprovider_myresource.test", "name", name),
                    resource.TestCheckTypeSetElemNestedAttrs("myprovider_myresource.test", "name", innerBlockMap),
                ),
            },
        },
    })
}

Solution

  • Try hclsyntax.ParseExpression and gohcl.DecodeExpression:

    package ...
    
    import (
        ...
        "testing"
    
        "github.com/hashicorp/hcl/v2"
        "github.com/hashicorp/hcl/v2/gohcl"
        "github.com/hashicorp/hcl/v2/hclsyntax"
    )
    
    func TestAccResource(t *testing.T) {
        ...
    
        innerBlock := `{
            field1 = 0
            field2 = false
            field4 = "value"
        }`
    
        expr, diag := hclsyntax.ParseExpression([]byte(innerBlock), "example.hcl", hcl.InitialPos)
        if diag.HasErrors() {
            t.Error(diag.Error())
        }
    
        var innerBlockMap map[string]string
        diag = gohcl.DecodeExpression(expr, nil, &innerBlockMap)
        if diag.HasErrors() {
            t.Error(diag.Error())
        }
    
        ...
    }