package corecfg import "gitea.epss.net.cn/klesh/ss/internal/automation" // deepMerge merges dict2 into dict1 in place and returns dict1, mirroring // corecfg_manager.py's module-level deep_merge(): nested maps recurse, // matching lists are concatenated, everything else is overwritten by dict2. func deepMerge(dict1, dict2 map[string]interface{}) map[string]interface{} { for k, v := range dict2 { existing, exists := dict1[k] if exists { existingMap, existingIsMap := existing.(map[string]interface{}) vMap, vIsMap := v.(map[string]interface{}) if existingIsMap && vIsMap { dict1[k] = deepMerge(existingMap, vMap) continue } existingList, existingIsList := existing.([]interface{}) vList, vIsList := v.([]interface{}) if existingIsList && vIsList { dict1[k] = append(existingList, vList...) continue } } dict1[k] = v } return dict1 } // popFirstProxyGroup removes and returns data["proxy-groups"]' first entry — // by convention a subscription's default selector group, the one its own // rules point at — so mergeProxySelection can fold every subscription's // default selector into one combined group. Returns nil if there is none. func popFirstProxyGroup(data map[string]interface{}) map[string]interface{} { groupsRaw, ok := data["proxy-groups"].([]interface{}) if !ok || len(groupsRaw) == 0 { return nil } group, ok := groupsRaw[0].(map[string]interface{}) if !ok { return nil } data["proxy-groups"] = groupsRaw[1:] return group } // selectionGroupName is the name given to the proxy-group produced by // folding every merged subscription's default selector group together. const selectionGroupName = "Proxy Selection" // mergeProxySelection collapses each subscription's default selector group // (already popped off by popFirstProxyGroup) into a single combined group // named selectionGroupName, covering every subscription's proxies, and // rewrites every rule/group reference to the old per-subscription groups so // they point at it instead. func mergeProxySelection(combined map[string]interface{}, groups []map[string]interface{}) { if len(groups) == 0 { return } rename := make(map[string]string, len(groups)) seen := make(map[string]bool) var groupType interface{} var mergedProxies []interface{} for _, group := range groups { if name, ok := group["name"].(string); ok { rename[name] = selectionGroupName } if groupType == nil { groupType = group["type"] } if list, ok := group["proxies"].([]interface{}); ok { for _, p := range list { name, ok := p.(string) if ok && seen[name] { continue } if ok { seen[name] = true } mergedProxies = append(mergedProxies, p) } } } merged := map[string]interface{}{ "name": selectionGroupName, "type": groupType, "proxies": mergedProxies, } existing, _ := combined["proxy-groups"].([]interface{}) combined["proxy-groups"] = append([]interface{}{merged}, existing...) automation.RewriteReferences(combined, rename) }