github.com/Cloud-Foundations/Dominator@v0.3.4/imagebuilder/builder/variables.go (about) 1 package builder 2 3 import ( 4 "os" 5 "strconv" 6 "strings" 7 ) 8 9 // expandExpression will expand the expression specified by expr and will 10 // perform parameter expansion on each sub-expression. The mappingFunc is used 11 // to lookup variables. 12 func expandExpression(expr string, mappingFunc func(string) string) string { 13 return os.Expand(expr, func(parameter string) string { 14 return expandVariable(parameter, mappingFunc) 15 }) 16 } 17 18 // expandVariable will expand the contents of the variable. If the specified 19 // variable is immediately followed by [<sep><start>:<end>] then it is split by 20 // the sep character, and then the components from start to end are joined. 21 // For example, [/2:-1] will remove the first two and last pathname components. 22 func expandVariable(variable string, mappingFunc func(string) string) string { 23 if len(variable) < 5 { 24 return mappingFunc(variable) // Not enough for a sub-expression. 25 } 26 if variable[len(variable)-1] != ']' { 27 return mappingFunc(variable) // Simple variable. 28 } 29 index := strings.IndexByte(variable, '[') 30 if index < 1 { 31 return "" 32 } 33 if len(variable) < index+4 { 34 return "" 35 } 36 variableName := variable[:index] 37 separator := variable[index+1 : index+2] 38 variableValue := mappingFunc(variableName) 39 if variableValue == "" { 40 return "" 41 } 42 splitValue := strings.Split(variableValue, separator) 43 splitRange := strings.Split(variable[index+2:len(variable)-1], ":") 44 if len(splitRange) != 2 { 45 return "" 46 } 47 var start, end int 48 var err error 49 if len(splitRange[0]) > 0 { 50 start, err = strconv.Atoi(splitRange[0]) 51 if err != nil { 52 return "" 53 } 54 } 55 if len(splitRange[1]) > 0 { 56 end, err = strconv.Atoi(splitRange[1]) 57 if err != nil { 58 return "" 59 } 60 if end >= len(splitValue) { 61 return "" 62 } 63 if end < 0 { 64 end += len(splitValue) 65 if end < start { 66 return "" 67 } 68 } 69 } else { 70 end = len(splitValue) 71 } 72 return strings.Join(splitValue[start:end], separator) 73 } 74 75 func (b *Builder) getVariableFunc( 76 extraVariables0, extraVariables1 map[string]string) func(string) string { 77 return func(varName string) string { 78 if extraVariables0 != nil { 79 if varValue, ok := extraVariables0[varName]; ok { 80 return varValue 81 } 82 } 83 if extraVariables1 != nil { 84 if varValue, ok := extraVariables1[varName]; ok { 85 return varValue 86 } 87 } 88 return b.variables[varName] 89 } 90 } 91 92 type variablesGetter map[string]string 93 94 func (vg variablesGetter) add(key, value string) { 95 if value != "" { 96 vg[key] = value 97 } 98 } 99 100 func (vg variablesGetter) copy() variablesGetter { 101 retval := make(variablesGetter, len(vg)) 102 for key, value := range vg { 103 retval[key] = value 104 } 105 return retval 106 } 107 108 func (vg variablesGetter) getenv() map[string]string { 109 return vg 110 } 111 112 func (vg variablesGetter) merge(vgToMerge variablesGetter) { 113 for key, value := range vgToMerge { 114 vg.add(key, value) 115 } 116 }