diff --git a/builder/digitalocean/builder.go b/builder/digitalocean/builder.go index 57e6018a1..3292bea10 100644 --- a/builder/digitalocean/builder.go +++ b/builder/digitalocean/builder.go @@ -66,7 +66,6 @@ type Config struct { stateTimeout time.Duration ctx *interpolate.Context - tpl *packer.ConfigTemplate } type Builder struct { diff --git a/packer/config_template.go b/packer/config_template.go deleted file mode 100644 index 47b096227..000000000 --- a/packer/config_template.go +++ /dev/null @@ -1,139 +0,0 @@ -package packer - -import ( - "bytes" - "fmt" - "os" - "strconv" - "strings" - "text/template" - "time" - - "github.com/mitchellh/packer/common/uuid" -) - -// InitTime is the UTC time when this package was initialized. It is -// used as the timestamp for all configuration templates so that they -// match for a single build. -var InitTime time.Time - -func init() { - InitTime = time.Now().UTC() -} - -// ConfigTemplate processes string data as a text/template with some common -// elements and functions available. Plugin creators should process as -// many fields as possible through this. -type ConfigTemplate struct { - UserVars map[string]string - - root *template.Template - i int -} - -// NewConfigTemplate creates a new configuration template processor. -func NewConfigTemplate() (*ConfigTemplate, error) { - result := &ConfigTemplate{ - UserVars: make(map[string]string), - } - - result.root = template.New("configTemplateRoot") - result.root.Funcs(template.FuncMap{ - "env": templateDisableEnv, - "pwd": templatePwd, - "isotime": templateISOTime, - "timestamp": templateTimestamp, - "user": result.templateUser, - "uuid": templateUuid, - "upper": strings.ToUpper, - "lower": strings.ToLower, - }) - - return result, nil -} - -// Process processes a single string, compiling and executing the template. -func (t *ConfigTemplate) Process(s string, data interface{}) (string, error) { - tpl, err := t.root.New(t.nextTemplateName()).Parse(s) - if err != nil { - return "", err - } - - buf := new(bytes.Buffer) - if err := tpl.Execute(buf, data); err != nil { - return "", err - } - - return buf.String(), nil -} - -// Validate the template. -func (t *ConfigTemplate) Validate(s string) error { - root, err := t.root.Clone() - if err != nil { - return err - } - - _, err = root.New("template").Parse(s) - return err -} - -// Add additional functions to the template -func (t *ConfigTemplate) Funcs(funcs template.FuncMap) { - t.root.Funcs(funcs) -} - -func (t *ConfigTemplate) nextTemplateName() string { - name := fmt.Sprintf("tpl%d", t.i) - t.i++ - return name -} - -// User is the function exposed as "user" within the templates and -// looks up user variables. -func (t *ConfigTemplate) templateUser(n string) (string, error) { - result, ok := t.UserVars[n] - if !ok { - return "", fmt.Errorf("unknown user var: %s", n) - } - - return result, nil -} - -func templateDisableEnv(n string) (string, error) { - return "", fmt.Errorf( - "Environmental variables can only be used as default values for user variables.") -} - -func templateDisableUser(n string) (string, error) { - return "", fmt.Errorf( - "User variable can't be used within a default value for a user variable: %s", n) -} - -func templateEnv(n string) string { - return os.Getenv(n) -} - -func templateISOTime(timeFormat ...string) (string, error) { - if len(timeFormat) == 0 { - return time.Now().UTC().Format(time.RFC3339), nil - } - - if len(timeFormat) > 1 { - return "", fmt.Errorf("too many values, 1 needed: %v", timeFormat) - } - - return time.Now().UTC().Format(timeFormat[0]), nil -} - -func templatePwd() (string, error) { - return os.Getwd() -} - -func templateTimestamp() string { - return strconv.FormatInt(InitTime.Unix(), 10) -} - -func templateUuid() string { - return uuid.TimeOrderedUUID() -} diff --git a/packer/config_template_test.go b/packer/config_template_test.go deleted file mode 100644 index cdc5fd461..000000000 --- a/packer/config_template_test.go +++ /dev/null @@ -1,214 +0,0 @@ -package packer - -import ( - "fmt" - "math" - "os" - "strconv" - "testing" - "time" -) - -func TestConfigTemplateProcess_env(t *testing.T) { - tpl, err := NewConfigTemplate() - if err != nil { - t.Fatalf("err: %s", err) - } - - _, err = tpl.Process(`{{env "foo"}}`, nil) - if err == nil { - t.Fatal("should error") - } -} - -func TestConfigTemplateProcess_isotime(t *testing.T) { - tpl, err := NewConfigTemplate() - if err != nil { - t.Fatalf("err: %s", err) - } - - result, err := tpl.Process(`{{isotime}}`, nil) - if err != nil { - t.Fatalf("err: %s", err) - } - - val, err := time.Parse(time.RFC3339, result) - if err != nil { - t.Fatalf("err: %s", err) - } - - currentTime := time.Now().UTC() - if currentTime.Sub(val) > 2*time.Second { - t.Fatalf("val: %d (current: %d)", val, currentTime) - } -} - -// Note must format with the magic Date: Mon Jan 2 15:04:05 -0700 MST 2006 -func TestConfigTemplateProcess_isotime_withFormat(t *testing.T) { - tpl, err := NewConfigTemplate() - if err != nil { - t.Fatalf("err: %s", err) - } - - // Checking for a too-many arguments error - // Because of the variadic function, compile time checking won't work - _, err = tpl.Process(`{{isotime "20060102" "huh"}}`, nil) - if err == nil { - t.Fatalf("err: cannot have more than 1 input") - } - - result, err := tpl.Process(`{{isotime "20060102"}}`, nil) - if err != nil { - t.Fatalf("err: %s", err) - } - - ti := time.Now().UTC() - val := fmt.Sprintf("%04d%02d%02d", ti.Year(), ti.Month(), ti.Day()) - - if result != val { - t.Fatalf("val: %s (formated: %s)", val, result) - } -} - -func TestConfigTemplateProcess_pwd(t *testing.T) { - tpl, err := NewConfigTemplate() - if err != nil { - t.Fatalf("err: %s", err) - } - - pwd, err := os.Getwd() - if err != nil { - t.Fatalf("err: %s", err) - } - - result, err := tpl.Process(`{{pwd}}`, nil) - if err != nil { - t.Fatalf("err: %s", err) - } - - if result != pwd { - t.Fatalf("err: %s", result) - } -} - -func TestConfigTemplateProcess_timestamp(t *testing.T) { - tpl, err := NewConfigTemplate() - if err != nil { - t.Fatalf("err: %s", err) - } - - result, err := tpl.Process(`{{timestamp}}`, nil) - if err != nil { - t.Fatalf("err: %s", err) - } - - val, err := strconv.ParseInt(result, 10, 64) - if err != nil { - t.Fatalf("err: %s", err) - } - - currentTime := time.Now().UTC().Unix() - if math.Abs(float64(currentTime-val)) > 10 { - t.Fatalf("val: %d (current: %d)", val, currentTime) - } - - time.Sleep(2 * time.Second) - - result2, err := tpl.Process(`{{timestamp}}`, nil) - if err != nil { - t.Fatalf("err: %s", err) - } - - if result != result2 { - t.Fatalf("bad: %#v %#v", result, result2) - } -} - -func TestConfigTemplateProcess_user(t *testing.T) { - tpl, err := NewConfigTemplate() - if err != nil { - t.Fatalf("err: %s", err) - } - - tpl.UserVars["foo"] = "bar" - - result, err := tpl.Process(`{{user "foo"}}`, nil) - if err != nil { - t.Fatalf("err: %s", err) - } - - if result != "bar" { - t.Fatalf("bad: %s", result) - } -} - -func TestConfigTemplateProcess_uuid(t *testing.T) { - tpl, err := NewConfigTemplate() - if err != nil { - t.Fatalf("err: %s", err) - } - - result, err := tpl.Process(`{{uuid}}`, nil) - if err != nil { - t.Fatalf("err: %s", err) - } - - if len(result) != 36 { - t.Fatalf("err: %s", result) - } -} - -func TestConfigTemplateProcess_upper(t *testing.T) { - tpl, err := NewConfigTemplate() - if err != nil { - t.Fatalf("err: %s", err) - } - - tpl.UserVars["foo"] = "bar" - - result, err := tpl.Process(`{{user "foo" | upper}}`, nil) - if err != nil { - t.Fatalf("err: %s", err) - } - - if result != "BAR" { - t.Fatalf("bad: %s", result) - } -} - -func TestConfigTemplateProcess_lower(t *testing.T) { - tpl, err := NewConfigTemplate() - if err != nil { - t.Fatalf("err: %s", err) - } - - tpl.UserVars["foo"] = "BAR" - - result, err := tpl.Process(`{{user "foo" | lower}}`, nil) - if err != nil { - t.Fatalf("err: %s", err) - } - - if result != "bar" { - t.Fatalf("bad: %s", result) - } -} - -func TestConfigTemplateValidate(t *testing.T) { - tpl, err := NewConfigTemplate() - if err != nil { - t.Fatalf("err: %s", err) - } - - // Valid - err = tpl.Validate(`{{user "foo"}}`) - if err != nil { - t.Fatalf("err: %s", err) - } - - // Invalid - err = tpl.Validate(`{{idontexist}}`) - if err == nil { - t.Fatal("should have error") - } -}