Merge pull request #1911 from hashicorp/b-template-diffs

provider/template: don't diff when there's no diff
This commit is contained in:
Mitchell Hashimoto 2015-05-11 16:34:09 -07:00
commit cc28d04777
3 changed files with 33 additions and 24 deletions

View File

@ -16,22 +16,23 @@ import (
func resource() *schema.Resource { func resource() *schema.Resource {
return &schema.Resource{ return &schema.Resource{
Create: Create, Create: Create,
Read: Read,
Update: Update,
Delete: Delete, Delete: Delete,
Exists: Exists, Exists: Exists,
Read: Read,
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"filename": &schema.Schema{ "filename": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
Description: "file to read template from", Description: "file to read template from",
ForceNew: true,
}, },
"vars": &schema.Schema{ "vars": &schema.Schema{
Type: schema.TypeMap, Type: schema.TypeMap,
Optional: true, Optional: true,
Default: make(map[string]interface{}), Default: make(map[string]interface{}),
Description: "variables to substitute", Description: "variables to substitute",
ForceNew: true,
}, },
"rendered": &schema.Schema{ "rendered": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
@ -42,43 +43,58 @@ func resource() *schema.Resource {
} }
} }
func Create(d *schema.ResourceData, meta interface{}) error { return eval(d) } func Create(d *schema.ResourceData, meta interface{}) error {
func Update(d *schema.ResourceData, meta interface{}) error { return eval(d) } rendered, err := render(d)
func Read(d *schema.ResourceData, meta interface{}) error { return nil } if err != nil {
return err
}
d.Set("rendered", rendered)
d.SetId(hash(rendered))
return nil
}
func Delete(d *schema.ResourceData, meta interface{}) error { func Delete(d *schema.ResourceData, meta interface{}) error {
d.SetId("") d.SetId("")
return nil return nil
} }
func Exists(d *schema.ResourceData, meta interface{}) (bool, error) { func Exists(d *schema.ResourceData, meta interface{}) (bool, error) {
// Reload every time in case something has changed. rendered, err := render(d)
// This should be cheap, and cache invalidation is hard. if err != nil {
return false, nil return false, err
}
return hash(rendered) == d.Id(), nil
}
func Read(d *schema.ResourceData, meta interface{}) error {
// Logic is handled in Exists, which only returns true if the rendered
// contents haven't changed. That means if we get here there's nothing to
// do.
return nil
} }
var readfile func(string) ([]byte, error) = ioutil.ReadFile // testing hook var readfile func(string) ([]byte, error) = ioutil.ReadFile // testing hook
func eval(d *schema.ResourceData) error { func render(d *schema.ResourceData) (string, error) {
filename := d.Get("filename").(string) filename := d.Get("filename").(string)
vars := d.Get("vars").(map[string]interface{}) vars := d.Get("vars").(map[string]interface{})
path, err := homedir.Expand(filename) path, err := homedir.Expand(filename)
if err != nil { if err != nil {
return err return "", err
} }
buf, err := readfile(path) buf, err := readfile(path)
if err != nil { if err != nil {
return err return "", err
} }
rendered, err := execute(string(buf), vars) rendered, err := execute(string(buf), vars)
if err != nil { if err != nil {
return fmt.Errorf("failed to render %v: %v", filename, err) return "", fmt.Errorf("failed to render %v: %v", filename, err)
} }
d.Set("rendered", rendered) return rendered, nil
d.SetId(hash(rendered))
return nil
} }
// execute parses and executes a template using vars. // execute parses and executes a template using vars.
@ -122,5 +138,5 @@ func execute(s string, vars map[string]interface{}) (string, error) {
func hash(s string) string { func hash(s string) string {
sha := sha256.Sum256([]byte(s)) sha := sha256.Sum256([]byte(s))
return hex.EncodeToString(sha[:])[:20] return hex.EncodeToString(sha[:])
} }

View File

@ -50,7 +50,6 @@ output "rendered" {
} }
return nil return nil
}, },
TransientResource: true,
}, },
}, },
}) })

View File

@ -75,12 +75,6 @@ type TestStep struct {
// Destroy will create a destroy plan if set to true. // Destroy will create a destroy plan if set to true.
Destroy bool Destroy bool
// TransientResource indicates that resources created as part
// of this test step are temporary and might be recreated anew
// with every planning step. This should only be set for
// pseudo-resources, like the null resource or templates.
TransientResource bool
} }
// Test performs an acceptance test on a resource. // Test performs an acceptance test on a resource.
@ -269,7 +263,7 @@ func testStep(
if p, err := ctx.Plan(); err != nil { if p, err := ctx.Plan(); err != nil {
return state, fmt.Errorf("Error on second follow-up plan: %s", err) return state, fmt.Errorf("Error on second follow-up plan: %s", err)
} else { } else {
if p.Diff != nil && !p.Diff.Empty() && !step.TransientResource { if p.Diff != nil && !p.Diff.Empty() {
return state, fmt.Errorf( return state, fmt.Errorf(
"After applying this step and refreshing, the plan was not empty:\n\n%s", p) "After applying this step and refreshing, the plan was not empty:\n\n%s", p)
} }