packer-cn/template/interpolate/funcs.go

175 lines
4.0 KiB
Go
Raw Normal View History

package interpolate
import (
"errors"
2015-05-16 00:12:54 -04:00
"fmt"
"os"
"path/filepath"
2015-05-16 00:14:41 -04:00
"strconv"
2015-05-16 00:16:52 -04:00
"strings"
"text/template"
2015-05-16 00:12:54 -04:00
"time"
2015-05-16 00:16:52 -04:00
2017-04-04 16:39:01 -04:00
"github.com/hashicorp/packer/common/uuid"
"github.com/hashicorp/packer/version"
)
2015-05-16 00:14:41 -04:00
// 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()
}
// Funcs are the interpolation funcs that are available within interpolations.
var FuncGens = map[string]FuncGenerator{
"build_name": funcGenBuildName,
"build_type": funcGenBuildType,
"env": funcGenEnv,
"isotime": funcGenIsotime,
"pwd": funcGenPwd,
"split": funcGenSplitter,
"template_dir": funcGenTemplateDir,
"timestamp": funcGenTimestamp,
"uuid": funcGenUuid,
"user": funcGenUser,
"packer_version": funcGenPackerVersion,
2015-05-16 00:16:52 -04:00
"upper": funcGenPrimitive(strings.ToUpper),
"lower": funcGenPrimitive(strings.ToLower),
}
// FuncGenerator is a function that given a context generates a template
// function for the template.
type FuncGenerator func(*Context) interface{}
// Funcs returns the functions that can be used for interpolation given
// a context.
func Funcs(ctx *Context) template.FuncMap {
result := make(map[string]interface{})
for k, v := range FuncGens {
result[k] = v(ctx)
}
if ctx != nil {
for k, v := range ctx.Funcs {
result[k] = v
}
}
return template.FuncMap(result)
}
func funcGenSplitter(ctx *Context) interface{} {
return func(k string, s string, i int) (string, error) {
// return func(s string) (string, error) {
split := strings.Split(k, s)
if len(split) <= i {
return "", fmt.Errorf("the substring %d was unavailable using the separator value, %s, only %d values were found", i, s, len(split))
}
return split[i], nil
}
}
func funcGenBuildName(ctx *Context) interface{} {
return func() (string, error) {
if ctx == nil || ctx.BuildName == "" {
return "", errors.New("build_name not available")
}
return ctx.BuildName, nil
}
}
func funcGenBuildType(ctx *Context) interface{} {
return func() (string, error) {
if ctx == nil || ctx.BuildType == "" {
return "", errors.New("build_type not available")
}
return ctx.BuildType, nil
}
}
func funcGenEnv(ctx *Context) interface{} {
return func(k string) (string, error) {
if !ctx.EnableEnv {
// The error message doesn't have to be that detailed since
// semantic checks should catch this.
return "", errors.New("env vars are not allowed here")
}
return os.Getenv(k), nil
}
}
2015-05-16 00:12:54 -04:00
func funcGenIsotime(ctx *Context) interface{} {
return func(format ...string) (string, error) {
if len(format) == 0 {
return InitTime.Format(time.RFC3339), nil
2015-05-16 00:12:54 -04:00
}
if len(format) > 1 {
return "", fmt.Errorf("too many values, 1 needed: %v", format)
}
return InitTime.Format(format[0]), nil
2015-05-16 00:12:54 -04:00
}
}
2015-05-16 00:16:52 -04:00
func funcGenPrimitive(value interface{}) FuncGenerator {
return func(ctx *Context) interface{} {
return value
}
}
2015-05-16 00:10:12 -04:00
func funcGenPwd(ctx *Context) interface{} {
return func() (string, error) {
return os.Getwd()
}
}
2015-05-29 17:29:32 -04:00
func funcGenTemplateDir(ctx *Context) interface{} {
return func() (string, error) {
if ctx == nil || ctx.TemplatePath == "" {
return "", errors.New("template path not available")
}
2015-05-29 17:29:32 -04:00
path, err := filepath.Abs(filepath.Dir(ctx.TemplatePath))
if err != nil {
return "", err
}
return path, nil
}
}
2015-05-16 00:14:41 -04:00
func funcGenTimestamp(ctx *Context) interface{} {
return func() string {
return strconv.FormatInt(InitTime.Unix(), 10)
}
}
func funcGenUser(ctx *Context) interface{} {
2017-02-04 02:15:18 -05:00
return func(k string) (string, error) {
2015-05-16 00:18:27 -04:00
if ctx == nil || ctx.UserVariables == nil {
2017-02-04 02:15:18 -05:00
return "", errors.New("test")
2015-05-16 00:18:27 -04:00
}
2017-02-04 02:15:18 -05:00
return ctx.UserVariables[k], nil
}
}
2015-05-16 00:16:52 -04:00
func funcGenUuid(ctx *Context) interface{} {
return func() string {
return uuid.TimeOrderedUUID()
}
}
func funcGenPackerVersion(ctx *Context) interface{} {
return func() string {
return version.FormattedVersion()
}
}