github.com/homburg/packer@v0.6.1-0.20140528012651-1dcaf1716848/packer/config_template.go (about) 1 package packer 2 3 import ( 4 "bytes" 5 "fmt" 6 "github.com/mitchellh/packer/common/uuid" 7 "os" 8 "strconv" 9 "text/template" 10 "time" 11 ) 12 13 // InitTime is the UTC time when this package was initialized. It is 14 // used as the timestamp for all configuration templates so that they 15 // match for a single build. 16 var InitTime time.Time 17 18 func init() { 19 InitTime = time.Now().UTC() 20 } 21 22 // ConfigTemplate processes string data as a text/template with some common 23 // elements and functions available. Plugin creators should process as 24 // many fields as possible through this. 25 type ConfigTemplate struct { 26 UserVars map[string]string 27 28 root *template.Template 29 i int 30 } 31 32 // NewConfigTemplate creates a new configuration template processor. 33 func NewConfigTemplate() (*ConfigTemplate, error) { 34 result := &ConfigTemplate{ 35 UserVars: make(map[string]string), 36 } 37 38 result.root = template.New("configTemplateRoot") 39 result.root.Funcs(template.FuncMap{ 40 "env": templateDisableEnv, 41 "pwd": templatePwd, 42 "isotime": templateISOTime, 43 "timestamp": templateTimestamp, 44 "user": result.templateUser, 45 "uuid": templateUuid, 46 }) 47 48 return result, nil 49 } 50 51 // Process processes a single string, compiling and executing the template. 52 func (t *ConfigTemplate) Process(s string, data interface{}) (string, error) { 53 tpl, err := t.root.New(t.nextTemplateName()).Parse(s) 54 if err != nil { 55 return "", err 56 } 57 58 buf := new(bytes.Buffer) 59 if err := tpl.Execute(buf, data); err != nil { 60 return "", err 61 } 62 63 return buf.String(), nil 64 } 65 66 // Validate the template. 67 func (t *ConfigTemplate) Validate(s string) error { 68 root, err := t.root.Clone() 69 if err != nil { 70 return err 71 } 72 73 _, err = root.New("template").Parse(s) 74 return err 75 } 76 77 // Add additional functions to the template 78 func (t *ConfigTemplate) Funcs(funcs template.FuncMap) { 79 t.root.Funcs(funcs) 80 } 81 82 func (t *ConfigTemplate) nextTemplateName() string { 83 name := fmt.Sprintf("tpl%d", t.i) 84 t.i++ 85 return name 86 } 87 88 // User is the function exposed as "user" within the templates and 89 // looks up user variables. 90 func (t *ConfigTemplate) templateUser(n string) (string, error) { 91 result, ok := t.UserVars[n] 92 if !ok { 93 return "", fmt.Errorf("uknown user var: %s", n) 94 } 95 96 return result, nil 97 } 98 99 func templateDisableEnv(n string) (string, error) { 100 return "", fmt.Errorf( 101 "Environmental variables can only be used as default values for user variables.") 102 } 103 104 func templateDisableUser(n string) (string, error) { 105 return "", fmt.Errorf( 106 "User variable can't be used within a default value for a user variable: %s", n) 107 } 108 109 func templateEnv(n string) string { 110 return os.Getenv(n) 111 } 112 113 func templateISOTime() string { 114 return InitTime.Format(time.RFC3339) 115 } 116 117 func templatePwd() (string, error) { 118 return os.Getwd() 119 } 120 121 func templateTimestamp() string { 122 return strconv.FormatInt(InitTime.Unix(), 10) 123 } 124 125 func templateUuid() string { 126 return uuid.TimeOrderedUUID() 127 }