diff --git a/builtin/providers/template/datasource_cloudinit_config.go b/builtin/providers/template/datasource_cloudinit_config.go index edbe0d13e..9fee9fb49 100644 --- a/builtin/providers/template/datasource_cloudinit_config.go +++ b/builtin/providers/template/datasource_cloudinit_config.go @@ -19,41 +19,41 @@ func dataSourceCloudinitConfig() *schema.Resource { Read: dataSourceCloudinitConfigRead, Schema: map[string]*schema.Schema{ - "part": &schema.Schema{ + "part": { Type: schema.TypeList, Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "content_type": &schema.Schema{ + "content_type": { Type: schema.TypeString, Optional: true, }, - "content": &schema.Schema{ + "content": { Type: schema.TypeString, Required: true, }, - "filename": &schema.Schema{ + "filename": { Type: schema.TypeString, Optional: true, }, - "merge_type": &schema.Schema{ + "merge_type": { Type: schema.TypeString, Optional: true, }, }, }, }, - "gzip": &schema.Schema{ + "gzip": { Type: schema.TypeBool, Optional: true, Default: true, }, - "base64_encode": &schema.Schema{ + "base64_encode": { Type: schema.TypeBool, Optional: true, Default: true, }, - "rendered": &schema.Schema{ + "rendered": { Type: schema.TypeString, Computed: true, Description: "rendered cloudinit configuration", @@ -84,7 +84,10 @@ func renderCloudinitConfig(d *schema.ResourceData) (string, error) { cloudInitParts := make(cloudInitParts, len(partsValue.([]interface{}))) for i, v := range partsValue.([]interface{}) { - p := v.(map[string]interface{}) + p, castOk := v.(map[string]interface{}) + if !castOk { + return "", fmt.Errorf("Unable to parse parts in cloudinit resource declaration") + } part := cloudInitPart{} if p, ok := p["content_type"]; ok { diff --git a/builtin/providers/template/datasource_cloudinit_config_test.go b/builtin/providers/template/datasource_cloudinit_config_test.go index e3e7225db..f40fc8392 100644 --- a/builtin/providers/template/datasource_cloudinit_config_test.go +++ b/builtin/providers/template/datasource_cloudinit_config_test.go @@ -3,6 +3,8 @@ package template import ( "testing" + "regexp" + r "github.com/hashicorp/terraform/helper/resource" ) @@ -58,7 +60,7 @@ func TestRender(t *testing.T) { r.UnitTest(t, r.TestCase{ Providers: testProviders, Steps: []r.TestStep{ - r.TestStep{ + { Config: tt.ResourceBlock, Check: r.ComposeTestCheckFunc( r.TestCheckResourceAttr("data.template_cloudinit_config.foo", "rendered", tt.Expected), @@ -69,12 +71,23 @@ func TestRender(t *testing.T) { } } -var testCloudInitConfig_basic = ` -data "template_cloudinit_config" "config" { - part { - content_type = "text/x-shellscript" - content = "baz" - } -}` +// From GH-13572, Correctly handle panic on a misconfigured cloudinit part +func TestRender_handlePanic(t *testing.T) { + r.UnitTest(t, r.TestCase{ + Providers: testProviders, + Steps: []r.TestStep{ + { + Config: testCloudInitConfig_misconfiguredParts, + ExpectError: regexp.MustCompile("Unable to parse parts in cloudinit resource declaration"), + }, + }, + }) +} -var testCloudInitConfig_basic_expected = `Content-Type: multipart/mixed; boundary=\"MIMEBOUNDARY\"\nMIME-Version: 1.0\r\n--MIMEBOUNDARY\r\nContent-Transfer-Encoding: 7bit\r\nContent-Type: text/x-shellscript\r\nMime-Version: 1.0\r\n\r\nbaz\r\n--MIMEBOUNDARY--\r\n` +var testCloudInitConfig_misconfiguredParts = ` +data "template_cloudinit_config" "foo" { + part { + content = "" + } +} +`