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 {
return &schema.Resource{
Create: Create,
Read: Read,
Update: Update,
Delete: Delete,
Exists: Exists,
Read: Read,
Schema: map[string]*schema.Schema{
"filename": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "file to read template from",
ForceNew: true,
},
"vars": &schema.Schema{
Type: schema.TypeMap,
Optional: true,
Default: make(map[string]interface{}),
Description: "variables to substitute",
ForceNew: true,
},
"rendered": &schema.Schema{
Type: schema.TypeString,
@ -42,43 +43,58 @@ func resource() *schema.Resource {
}
}
func Create(d *schema.ResourceData, meta interface{}) error { return eval(d) }
func Update(d *schema.ResourceData, meta interface{}) error { return eval(d) }
func Read(d *schema.ResourceData, meta interface{}) error { return nil }
func Create(d *schema.ResourceData, meta interface{}) error {
rendered, err := render(d)
if err != nil {
return err
}
d.Set("rendered", rendered)
d.SetId(hash(rendered))
return nil
}
func Delete(d *schema.ResourceData, meta interface{}) error {
d.SetId("")
return nil
}
func Exists(d *schema.ResourceData, meta interface{}) (bool, error) {
// Reload every time in case something has changed.
// This should be cheap, and cache invalidation is hard.
return false, nil
rendered, err := render(d)
if err != 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
func eval(d *schema.ResourceData) error {
func render(d *schema.ResourceData) (string, error) {
filename := d.Get("filename").(string)
vars := d.Get("vars").(map[string]interface{})
path, err := homedir.Expand(filename)
if err != nil {
return err
return "", err
}
buf, err := readfile(path)
if err != nil {
return err
return "", err
}
rendered, err := execute(string(buf), vars)
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)
d.SetId(hash(rendered))
return nil
return rendered, nil
}
// 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 {
sha := sha256.Sum256([]byte(s))
return hex.EncodeToString(sha[:])[:20]
return hex.EncodeToString(sha[:])
}

View File

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

View File

@ -75,12 +75,6 @@ type TestStep struct {
// Destroy will create a destroy plan if set to true.
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.
@ -269,7 +263,7 @@ func testStep(
if p, err := ctx.Plan(); err != nil {
return state, fmt.Errorf("Error on second follow-up plan: %s", err)
} else {
if p.Diff != nil && !p.Diff.Empty() && !step.TransientResource {
if p.Diff != nil && !p.Diff.Empty() {
return state, fmt.Errorf(
"After applying this step and refreshing, the plan was not empty:\n\n%s", p)
}