Include content option for file provisioner

- Include new option in file provisioner. Now content or source can be
  provided. Content will create a temp file and copy there the contents.
- Later that file will be used as source.
- Include test to check that changes are working correctly.
This commit is contained in:
jorge.marey 2015-11-13 12:50:31 +01:00 committed by James Nugent
parent 2a45b1fb25
commit 9b065f32e2
2 changed files with 82 additions and 17 deletions

View File

@ -2,12 +2,12 @@ package file
import ( import (
"fmt" "fmt"
"io/ioutil"
"log" "log"
"os" "os"
"time" "time"
"github.com/hashicorp/terraform/communicator" "github.com/hashicorp/terraform/communicator"
"github.com/hashicorp/terraform/helper/config"
"github.com/hashicorp/terraform/terraform" "github.com/hashicorp/terraform/terraform"
"github.com/mitchellh/go-homedir" "github.com/mitchellh/go-homedir"
) )
@ -26,18 +26,13 @@ func (p *ResourceProvisioner) Apply(
return err return err
} }
// Get the source and destination // Get the source
sRaw := c.Config["source"] src, err := p.getSrc(c)
src, ok := sRaw.(string)
if !ok {
return fmt.Errorf("Unsupported 'source' type! Must be string.")
}
src, err = homedir.Expand(src)
if err != nil { if err != nil {
return err return err
} }
// Get destination
dRaw := c.Config["destination"] dRaw := c.Config["destination"]
dst, ok := dRaw.(string) dst, ok := dRaw.(string)
if !ok { if !ok {
@ -48,13 +43,52 @@ func (p *ResourceProvisioner) Apply(
// Validate checks if the required arguments are configured // Validate checks if the required arguments are configured
func (p *ResourceProvisioner) Validate(c *terraform.ResourceConfig) (ws []string, es []error) { func (p *ResourceProvisioner) Validate(c *terraform.ResourceConfig) (ws []string, es []error) {
v := &config.Validator{ numDst := 0
Required: []string{ numSrc := 0
"source", for name := range c.Raw {
"destination", switch name {
}, case "destination":
numDst++
case "source", "content":
numSrc++
default:
es = append(es, fmt.Errorf("Unknown configuration '%s'", name))
}
} }
return v.Validate(c) if numSrc != 1 || numDst != 1 {
es = append(es, fmt.Errorf("Must provide one of 'content' or 'source' and 'destination' to file"))
}
return
}
// getSrc returns the file to use as source
func (p *ResourceProvisioner) getSrc(c *terraform.ResourceConfig) (string, error) {
var src string
sRaw, ok := c.Config["source"]
if ok {
if src, ok = sRaw.(string); !ok {
return "", fmt.Errorf("Unsupported 'source' type! Must be string.")
}
}
content, ok := c.Config["content"]
if ok {
file, err := ioutil.TempFile("", "tf-file-content")
if err != nil {
return "", err
}
contentStr, ok := content.(string)
if !ok {
return "", fmt.Errorf("Unsupported 'content' type! Must be string.")
}
if _, err = file.WriteString(contentStr); err != nil {
return "", err
}
src = file.Name()
}
return homedir.Expand(src)
} }
// copyFiles is used to copy the files from a source to a destination // copyFiles is used to copy the files from a source to a destination

View File

@ -11,7 +11,7 @@ func TestResourceProvisioner_impl(t *testing.T) {
var _ terraform.ResourceProvisioner = new(ResourceProvisioner) var _ terraform.ResourceProvisioner = new(ResourceProvisioner)
} }
func TestResourceProvider_Validate_good(t *testing.T) { func TestResourceProvider_Validate_good_source(t *testing.T) {
c := testConfig(t, map[string]interface{}{ c := testConfig(t, map[string]interface{}{
"source": "/tmp/foo", "source": "/tmp/foo",
"destination": "/tmp/bar", "destination": "/tmp/bar",
@ -26,7 +26,22 @@ func TestResourceProvider_Validate_good(t *testing.T) {
} }
} }
func TestResourceProvider_Validate_bad(t *testing.T) { func TestResourceProvider_Validate_good_content(t *testing.T) {
c := testConfig(t, map[string]interface{}{
"content": "value to copy",
"destination": "/tmp/bar",
})
p := new(ResourceProvisioner)
warn, errs := p.Validate(c)
if len(warn) > 0 {
t.Fatalf("Warnings: %v", warn)
}
if len(errs) > 0 {
t.Fatalf("Errors: %v", errs)
}
}
func TestResourceProvider_Validate_bad_not_destination(t *testing.T) {
c := testConfig(t, map[string]interface{}{ c := testConfig(t, map[string]interface{}{
"source": "nope", "source": "nope",
}) })
@ -40,6 +55,22 @@ func TestResourceProvider_Validate_bad(t *testing.T) {
} }
} }
func TestResourceProvider_Validate_bad_to_many_src(t *testing.T) {
c := testConfig(t, map[string]interface{}{
"source": "nope",
"content": "value to copy",
"destination": "/tmp/bar",
})
p := new(ResourceProvisioner)
warn, errs := p.Validate(c)
if len(warn) > 0 {
t.Fatalf("Warnings: %v", warn)
}
if len(errs) == 0 {
t.Fatalf("Should have errors")
}
}
func testConfig( func testConfig(
t *testing.T, t *testing.T,
c map[string]interface{}) *terraform.ResourceConfig { c map[string]interface{}) *terraform.ResourceConfig {