github.com/swaros/contxt/module/taskrun@v0.0.0-20240305083542-3dbd4436ac40/placeholder.go (about) 1 // Copyright (c) 2020 Thomas Ziegler <thomas.zglr@googlemail.com>. All rights reserved. 2 // 3 // Licensed under the MIT License 4 // 5 // 6 // Permission is hereby granted, free of charge, to any person obtaining a copy 7 // of this software and associated documentation files (the "Software"), to deal 8 // in the Software without restriction, including without limitation the rights 9 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 // copies of the Software, and to permit persons to whom the Software is 11 // furnished to do so, subject to the following conditions: 12 // 13 // The above copyright notice and this permission notice shall be included in all 14 // copies or substantial portions of the Software. 15 // 16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 // SOFTWARE. 23 package taskrun 24 25 import ( 26 "os" 27 "strings" 28 "sync" 29 30 "github.com/sirupsen/logrus" 31 ) 32 33 var keyValue sync.Map 34 35 // SetPH add key value pair 36 func SetPH(key, value string) { 37 GetLogger().WithField(key, value).Trace("add/overwrite placeholder") 38 keyValue.Store(key, value) 39 } 40 41 func AppendToPH(key, value string) bool { 42 if val, ok := keyValue.Load(key); ok { 43 value = val.(string) + value 44 keyValue.Store(key, value) 45 return true 46 } 47 return false 48 } 49 50 func SetIfNotExists(key, value string) { 51 _, ok := keyValue.Load(key) 52 if !ok { 53 keyValue.Store(key, value) 54 } 55 56 } 57 58 // GetPH the content of the key as string. if exists. 59 func GetPHExists(key string) (string, bool) { 60 result, ok := keyValue.Load(key) 61 if ok { 62 return result.(string), ok 63 } 64 return "", ok 65 } 66 67 // GetPH the content of the key. but at least a empty 68 // string if not exists. so this is not usefull 69 // to test if the PH was set. 70 func GetPH(key string) string { 71 result, ok := keyValue.Load(key) 72 if ok { 73 GetLogger().WithField(key, result.(string)).Trace("deliver content from placeholder") 74 return result.(string) 75 } 76 GetLogger().WithField("key", key).Trace("returns empty string because key is not set") 77 return "" 78 } 79 80 func GetPlaceHoldersFnc(inspectFunc func(phKey string, phValue string)) { 81 keyValue.Range(func(key, value any) bool { 82 inspectFunc(key.(string), value.(string)) 83 return true 84 }) 85 } 86 87 // HandlePlaceHolder replaces all defined placeholders 88 func HandlePlaceHolder(line string) string { 89 var scopeVars map[string]string = make(map[string]string) 90 for { 91 return handlePlaceHolder(line, scopeVars) 92 } 93 } 94 95 func HandlePlaceHolderWithScope(line string, scopeVars map[string]string) string { 96 for { 97 return handlePlaceHolder(line, scopeVars) 98 } 99 } 100 101 func handlePlaceHolder(line string, scopeVars map[string]string) string { 102 103 // this block is for logging at trace level only 104 if GetLogger().IsLevelEnabled(logrus.TraceLevel) { 105 106 for key, value := range scopeVars { 107 keyName := "${" + key + "}" 108 if strings.Contains(line, keyName) { 109 GetLogger().WithField("line", line).Trace("scope replace: source") 110 GetLogger().WithField(keyName, value).Trace("scope replace: variables") 111 } 112 line = strings.ReplaceAll(line, keyName, value) 113 } 114 115 keyValue.Range(func(key, value interface{}) bool { 116 keyName := "${" + key.(string) + "}" 117 if strings.Contains(line, keyName) { 118 GetLogger().WithField("line", line).Trace("replace: source") 119 GetLogger().WithField(keyName, value.(string)).Trace("replace: variables") 120 } 121 line = strings.ReplaceAll(line, keyName, value.(string)) 122 line = handleMapVars(line) 123 return true 124 }) 125 } 126 127 for key, value := range scopeVars { 128 keyName := "${" + key + "}" 129 line = strings.ReplaceAll(line, keyName, value) 130 } 131 132 keyValue.Range(func(key, value interface{}) bool { 133 keyName := "${" + key.(string) + "}" 134 line = strings.ReplaceAll(line, keyName, value.(string)) 135 return true 136 }) 137 138 line = handleMapVars(line) 139 for _, value := range os.Environ() { 140 pair := strings.SplitN(value, "=", 2) 141 if len(pair) == 2 { 142 key := pair[0] 143 val := pair[1] 144 keyName := "${" + key + "}" 145 line = strings.ReplaceAll(line, keyName, val) 146 } 147 } 148 return line 149 } 150 151 func handleMapVars(line string) string { 152 dataKeys := GetDataKeys() 153 if len(dataKeys) == 0 { 154 return line 155 } 156 GetLogger().WithField("key-count", len(dataKeys)).Trace("parsing keymap placeholder") 157 for _, keyname := range dataKeys { 158 lookup := "${" + keyname + ":" 159 if strings.Contains(line, lookup) { 160 start := strings.Index(line, lookup) 161 if start > -1 { 162 end := strings.Index(line[start:], "}") 163 if end > -1 { 164 pathLine := line[start+len(lookup) : start+end] 165 if pathLine != "" { 166 replace := lookup + pathLine + "}" 167 GetLogger().Debug("replace ", replace) 168 line = strings.ReplaceAll(line, replace, GetJSONPathValueString(keyname, pathLine)) 169 } 170 } else { 171 GetLogger().WithField("key", lookup).Warn("error by getting end position of prefix") 172 } 173 } else { 174 GetLogger().WithField("key", lookup).Warn("error by getting start position of prefix") 175 } 176 } 177 } 178 return line 179 } 180 181 // ClearAll removes all entries 182 func ClearAll() { 183 keyValue.Range(func(key, _ interface{}) bool { 184 keyValue.Delete(key) 185 return true 186 }) 187 watchTaskList.Range(func(key, _ interface{}) bool { 188 keyValue.Delete(key) 189 return true 190 }) 191 }