github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/pkg/config/interpolation/interpolation.go (about) 1 package interpolation 2 3 import ( 4 "fmt" 5 "regexp" 6 "strings" 7 8 "github.com/SAP/jenkins-library/pkg/log" 9 ) 10 11 const ( 12 maxLookupDepth = 10 13 ) 14 15 var ( 16 lookupRegex *regexp.Regexp = regexp.MustCompile(`\$\((?P<property>[a-zA-Z0-9\.]*)\)`) 17 captureGroups = setupCaptureGroups(lookupRegex.SubexpNames()) 18 ) 19 20 // ResolveMap interpolates every string value of a map and tries to lookup references to other properties of that map 21 func ResolveMap(config map[string]interface{}) bool { 22 for key, value := range config { 23 if str, ok := value.(string); ok { 24 resolvedStr, ok := ResolveString(str, config) 25 if !ok { 26 return false 27 } 28 config[key] = resolvedStr 29 } 30 } 31 return true 32 } 33 34 func resolveString(str string, lookupMap map[string]interface{}, n int) (string, bool) { 35 matches := lookupRegex.FindAllStringSubmatch(str, -1) 36 if len(matches) == 0 { 37 return str, true 38 } 39 if n == maxLookupDepth { 40 log.Entry().Errorf("Property could not be resolved with a depth of %d. '%s' is still left to resolve", n, str) 41 return "", false 42 } 43 for _, match := range matches { 44 property := match[captureGroups["property"]] 45 if propVal, ok := lookupMap[property]; ok { 46 str = strings.ReplaceAll(str, fmt.Sprintf("$(%s)", property), propVal.(string)) 47 } else { 48 // value not found 49 log.Entry().Debugf("Can't interploate '%s'. Missing property '%s'", str, property) 50 return "", false 51 } 52 } 53 return resolveString(str, lookupMap, n+1) 54 } 55 56 // ResolveString takes a string and replaces all references inside of it with values from the given lookupMap. 57 // This is being done recursively until the maxLookupDepth is reached. 58 func ResolveString(str string, lookupMap map[string]interface{}) (string, bool) { 59 return resolveString(str, lookupMap, 0) 60 } 61 62 func setupCaptureGroups(captureGroupsList []string) map[string]int { 63 groups := make(map[string]int, len(captureGroupsList)) 64 for i, captureGroupName := range captureGroupsList { 65 if i == 0 { 66 continue 67 } 68 groups[captureGroupName] = i 69 } 70 return groups 71 }