github.com/GuanceCloud/cliutils@v1.1.21/pipeline/manager/scriptstore.go (about) 1 // Unless explicitly stated otherwise all files in this repository are licensed 2 // under the MIT License. 3 // This product includes software developed at Guance Cloud (https://www.guance.com/). 4 // Copyright 2021-present Guance, Inc. 5 6 package manager 7 8 import ( 9 "path/filepath" 10 "sync" 11 "time" 12 13 "github.com/GuanceCloud/cliutils/logger" 14 "github.com/GuanceCloud/cliutils/pipeline/ptinput/plmap" 15 "github.com/GuanceCloud/cliutils/pipeline/stats" 16 "github.com/GuanceCloud/cliutils/point" 17 ) 18 19 var log = logger.DefaultSLogger("pl-script") 20 21 const ( 22 NSDefault = "default" // 内置 pl script, 优先级最低 23 NSGitRepo = "gitrepo" // git 管理的 pl script 24 NSConfd = "confd" // confd 管理的 pl script 25 NSRemote = "remote" // remote pl script,优先级最高 26 ) 27 28 var nsSearchOrder = [4]string{ 29 NSRemote, // 优先级最高的 ns 30 NSConfd, 31 NSGitRepo, 32 NSDefault, 33 } 34 35 func InitLog() { 36 log = logger.SLogger("pl-script") 37 } 38 39 func InitStore(manager *Manager, installDir string, tags map[string]string) { 40 stats.InitLog() 41 42 plPath := filepath.Join(installDir, "pipeline") 43 manager.LoadScriptsFromWorkspace(NSDefault, plPath, tags) 44 } 45 46 func NSFindPriority(ns string) int { 47 switch ns { 48 case NSDefault: 49 return 0 // lowest priority 50 case NSGitRepo: 51 return 1 52 case NSConfd: 53 return 2 54 case NSRemote: 55 return 3 56 default: 57 return -1 58 } 59 } 60 61 type ScriptStore struct { 62 category point.Category 63 64 storage scriptStorage 65 66 defultScript string 67 68 index map[string]*PlScript 69 indexLock sync.RWMutex 70 71 cfg ManagerCfg 72 } 73 74 type scriptStorage struct { 75 sync.RWMutex 76 scripts map[string](map[string]*PlScript) 77 } 78 79 func NewScriptStore(category point.Category, cfg ManagerCfg) *ScriptStore { 80 return &ScriptStore{ 81 category: category, 82 storage: scriptStorage{ 83 scripts: map[string]map[string]*PlScript{ 84 NSRemote: {}, 85 NSConfd: {}, 86 NSGitRepo: {}, 87 NSDefault: {}, 88 }, 89 }, 90 index: map[string]*PlScript{}, 91 cfg: cfg, 92 } 93 } 94 95 func (store *ScriptStore) SetDefaultScript(name string) { 96 store.indexLock.Lock() 97 defer store.indexLock.Unlock() 98 store.defultScript = name 99 } 100 101 func (store *ScriptStore) GetDefaultScript() string { 102 store.indexLock.RLock() 103 defer store.indexLock.RUnlock() 104 return store.defultScript 105 } 106 107 func (store *ScriptStore) IndexGet(name string) (*PlScript, bool) { 108 store.indexLock.RLock() 109 defer store.indexLock.RUnlock() 110 if v, ok := store.index[name]; ok { 111 return v, ok 112 } 113 return nil, false 114 } 115 116 func (store *ScriptStore) IndexDefault() (*PlScript, bool) { 117 store.indexLock.RLock() 118 defer store.indexLock.RUnlock() 119 120 if v, ok := store.index[store.defultScript]; ok { 121 return v, ok 122 } 123 return nil, false 124 } 125 126 func (store *ScriptStore) Count() int { 127 store.storage.RLock() 128 defer store.storage.RUnlock() 129 130 return len(store.storage.scripts[NSRemote]) + 131 len(store.storage.scripts[NSConfd]) + 132 len(store.storage.scripts[NSGitRepo]) + 133 len(store.storage.scripts[NSDefault]) 134 } 135 136 func (store *ScriptStore) GetWithNs(name, ns string) (*PlScript, bool) { 137 store.storage.RLock() 138 defer store.storage.RUnlock() 139 if s, ok := store.storage.scripts[ns][name]; ok { 140 return s, ok 141 } 142 return nil, false 143 } 144 145 func (store *ScriptStore) indexStore(script *PlScript) { 146 store.indexLock.Lock() 147 defer store.indexLock.Unlock() 148 149 if store.index == nil { 150 store.index = map[string]*PlScript{} 151 } 152 store.index[script.name] = script 153 } 154 155 func (store *ScriptStore) indexDelete(name string) { 156 store.indexLock.Lock() 157 defer store.indexLock.Unlock() 158 159 delete(store.index, name) 160 } 161 162 func (store *ScriptStore) indexUpdate(script *PlScript) { 163 if script == nil { 164 return 165 } 166 167 curScript, ok := store.IndexGet(script.name) 168 169 if !ok { 170 store.indexStore(script) 171 172 stats.WriteUpdateTime(script.tags) 173 stats.WriteEvent(&stats.ChangeEvent{ 174 Name: script.name, 175 Category: script.category, 176 NS: script.ns, 177 Script: script.script, 178 Op: stats.EventOpIndex, 179 Time: time.Now(), 180 }, script.tags) 181 return 182 } 183 184 nsCur := NSFindPriority(curScript.ns) 185 nsNew := NSFindPriority(script.ns) 186 if nsNew >= nsCur { 187 store.indexStore(script) 188 stats.WriteUpdateTime(curScript.tags) 189 stats.WriteUpdateTime(script.tags) 190 stats.WriteEvent(&stats.ChangeEvent{ 191 Name: script.name, 192 Category: script.category, 193 NS: script.ns, 194 NSOld: curScript.ns, 195 Script: script.script, 196 ScriptOld: curScript.script, 197 Op: stats.EventOpIndexUpdate, 198 Time: time.Now(), 199 }, script.tags) 200 } 201 } 202 203 func (store *ScriptStore) indexDeleteAndBack(name, ns string, scripts4back map[string](map[string]*PlScript)) { 204 curScript, ok := store.IndexGet(name) 205 if !ok { 206 return 207 } 208 209 nsCur := NSFindPriority(curScript.ns) 210 if NSFindPriority(ns) != nsCur { 211 return 212 } 213 214 if nsCur > len(nsSearchOrder) { 215 return 216 } 217 218 if nsCur == -1 { 219 store.indexDelete(name) 220 221 stats.WriteEvent(&stats.ChangeEvent{ 222 Name: name, 223 Category: curScript.category, 224 NS: curScript.ns, 225 Script: curScript.script, 226 Op: stats.EventOpIndexDelete, 227 Time: time.Now(), 228 }, curScript.tags) 229 return 230 } 231 232 for _, v := range nsSearchOrder[len(nsSearchOrder)-nsCur:] { 233 if v, ok := scripts4back[v]; ok { 234 if s, ok := v[name]; ok { 235 store.indexStore(s) 236 stats.WriteUpdateTime(s.tags) 237 stats.WriteEvent(&stats.ChangeEvent{ 238 Name: name, 239 Category: s.category, 240 NS: s.ns, 241 NSOld: curScript.ns, 242 Script: s.script, 243 ScriptOld: curScript.script, 244 Op: stats.EventOpIndexDeleteAndBack, 245 Time: time.Now(), 246 }, s.tags) 247 return 248 } 249 } 250 } 251 252 store.indexDelete(name) 253 254 stats.WriteEvent(&stats.ChangeEvent{ 255 Name: name, 256 Category: curScript.category, 257 NS: curScript.ns, 258 Script: curScript.script, 259 Op: stats.EventOpIndexDelete, 260 Time: time.Now(), 261 }, curScript.tags) 262 } 263 264 func (store *ScriptStore) UpdateScriptsWithNS(ns string, 265 namedScript, scriptTags map[string]string, 266 ) map[string]error { 267 store.storage.Lock() 268 defer store.storage.Unlock() 269 270 if _, ok := store.storage.scripts[ns]; !ok { 271 store.storage.scripts[ns] = map[string]*PlScript{} 272 } 273 274 aggBuk := plmap.NewAggBuks(store.cfg.upFn, store.cfg.gTags) 275 retScripts, retErr := NewScripts(namedScript, scriptTags, ns, store.category, 276 aggBuk) 277 278 for name, err := range retErr { 279 var errStr string 280 if err != nil { 281 errStr = err.Error() 282 } 283 change := stats.ChangeEvent{ 284 Name: name, 285 Category: store.category, 286 NS: ns, 287 Script: namedScript[name], 288 Op: stats.EventOpCompileError, 289 Time: time.Now(), 290 CompileError: errStr, 291 } 292 293 sTags := map[string]string{ 294 "name": name, 295 "ns": ns, 296 "lang": "platypus", 297 "category": store.category.String(), 298 } 299 300 for k, v := range scriptTags { 301 if _, ok := sTags[k]; !ok { 302 sTags[k] = v 303 } 304 } 305 306 stats.WriteUpdateTime(sTags) 307 store.indexDeleteAndBack(name, ns, store.storage.scripts) 308 309 if v, ok := store.storage.scripts[ns][name]; ok { 310 if v.plBuks != nil { 311 v.plBuks.StopAllBukScanner() 312 } 313 if v.cache != nil { 314 v.cache.Stop() 315 } 316 if v.ptWindow != nil { 317 v.ptWindow.Deprecated() 318 } 319 delete(store.storage.scripts[ns], name) 320 } 321 stats.WriteEvent(&change, sTags) 322 } 323 324 // 如果上一次的集合中的脚本不存在于当前结果,则删除 325 for name, curScript := range store.storage.scripts[ns] { 326 if newScript, ok := retScripts[name]; ok { // 有更新 327 store.storage.scripts[ns][name] = newScript 328 stats.WriteUpdateTime(newScript.tags) 329 store.indexUpdate(newScript) 330 } else { // 删除 331 stats.WriteUpdateTime(curScript.tags) 332 store.indexDeleteAndBack(name, ns, store.storage.scripts) 333 delete(store.storage.scripts[ns], name) 334 } 335 336 // 清理之前一个脚本的资源 337 if curScript.plBuks != nil { 338 curScript.plBuks.StopAllBukScanner() 339 } 340 if curScript.cache != nil { 341 curScript.cache.Stop() 342 } 343 if curScript.ptWindow != nil { 344 curScript.ptWindow.Deprecated() 345 } 346 } 347 348 // 执行新增操作 349 for name, newScript := range retScripts { 350 if _, ok := store.storage.scripts[ns][name]; !ok { 351 store.storage.scripts[ns][name] = newScript 352 stats.WriteUpdateTime(newScript.tags) 353 store.indexUpdate(newScript) 354 } 355 } 356 357 if len(retErr) > 0 { 358 return retErr 359 } 360 return nil 361 }