github.com/aspring/packer@v0.8.1-0.20150629211158-9db281ac0f89/template/interpolate/funcs.go (about)

     1  package interpolate
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"os"
     7  	"path/filepath"
     8  	"strconv"
     9  	"strings"
    10  	"text/template"
    11  	"time"
    12  
    13  	"github.com/mitchellh/packer/common/uuid"
    14  )
    15  
    16  // InitTime is the UTC time when this package was initialized. It is
    17  // used as the timestamp for all configuration templates so that they
    18  // match for a single build.
    19  var InitTime time.Time
    20  
    21  func init() {
    22  	InitTime = time.Now().UTC()
    23  }
    24  
    25  // Funcs are the interpolation funcs that are available within interpolations.
    26  var FuncGens = map[string]FuncGenerator{
    27  	"build_name":   funcGenBuildName,
    28  	"build_type":   funcGenBuildType,
    29  	"env":          funcGenEnv,
    30  	"isotime":      funcGenIsotime,
    31  	"pwd":          funcGenPwd,
    32  	"template_dir": funcGenTemplateDir,
    33  	"timestamp":    funcGenTimestamp,
    34  	"uuid":         funcGenUuid,
    35  	"user":         funcGenUser,
    36  
    37  	"upper": funcGenPrimitive(strings.ToUpper),
    38  	"lower": funcGenPrimitive(strings.ToLower),
    39  }
    40  
    41  // FuncGenerator is a function that given a context generates a template
    42  // function for the template.
    43  type FuncGenerator func(*Context) interface{}
    44  
    45  // Funcs returns the functions that can be used for interpolation given
    46  // a context.
    47  func Funcs(ctx *Context) template.FuncMap {
    48  	result := make(map[string]interface{})
    49  	for k, v := range FuncGens {
    50  		result[k] = v(ctx)
    51  	}
    52  	if ctx != nil {
    53  		for k, v := range ctx.Funcs {
    54  			result[k] = v
    55  		}
    56  	}
    57  
    58  	return template.FuncMap(result)
    59  }
    60  
    61  func funcGenBuildName(ctx *Context) interface{} {
    62  	return func() (string, error) {
    63  		if ctx == nil || ctx.BuildName == "" {
    64  			return "", errors.New("build_name not available")
    65  		}
    66  
    67  		return ctx.BuildName, nil
    68  	}
    69  }
    70  
    71  func funcGenBuildType(ctx *Context) interface{} {
    72  	return func() (string, error) {
    73  		if ctx == nil || ctx.BuildType == "" {
    74  			return "", errors.New("build_name not available")
    75  		}
    76  
    77  		return ctx.BuildType, nil
    78  	}
    79  }
    80  
    81  func funcGenEnv(ctx *Context) interface{} {
    82  	return func(k string) (string, error) {
    83  		if !ctx.EnableEnv {
    84  			// The error message doesn't have to be that detailed since
    85  			// semantic checks should catch this.
    86  			return "", errors.New("env vars are not allowed here")
    87  		}
    88  
    89  		return os.Getenv(k), nil
    90  	}
    91  }
    92  
    93  func funcGenIsotime(ctx *Context) interface{} {
    94  	return func(format ...string) (string, error) {
    95  		if len(format) == 0 {
    96  			return time.Now().UTC().Format(time.RFC3339), nil
    97  		}
    98  
    99  		if len(format) > 1 {
   100  			return "", fmt.Errorf("too many values, 1 needed: %v", format)
   101  		}
   102  
   103  		return time.Now().UTC().Format(format[0]), nil
   104  	}
   105  }
   106  
   107  func funcGenPrimitive(value interface{}) FuncGenerator {
   108  	return func(ctx *Context) interface{} {
   109  		return value
   110  	}
   111  }
   112  
   113  func funcGenPwd(ctx *Context) interface{} {
   114  	return func() (string, error) {
   115  		return os.Getwd()
   116  	}
   117  }
   118  
   119  func funcGenTemplateDir(ctx *Context) interface{} {
   120  	return func() (string, error) {
   121  		if ctx == nil || ctx.TemplatePath == "" {
   122  			return "", errors.New("template path not available")
   123  		}
   124  
   125  		path, err := filepath.Abs(filepath.Dir(ctx.TemplatePath))
   126  		if err != nil {
   127  			return "", err
   128  		}
   129  
   130  		return path, nil
   131  	}
   132  }
   133  
   134  func funcGenTimestamp(ctx *Context) interface{} {
   135  	return func() string {
   136  		return strconv.FormatInt(InitTime.Unix(), 10)
   137  	}
   138  }
   139  
   140  func funcGenUser(ctx *Context) interface{} {
   141  	return func(k string) string {
   142  		if ctx == nil || ctx.UserVariables == nil {
   143  			return ""
   144  		}
   145  
   146  		return ctx.UserVariables[k]
   147  	}
   148  }
   149  
   150  func funcGenUuid(ctx *Context) interface{} {
   151  	return func() string {
   152  		return uuid.TimeOrderedUUID()
   153  	}
   154  }