package automation import "fmt" // buildProxyGroups implements the "proxy-groups" ssm feature: for each rule, // filter the merged proxy pool by rule.Match and append a new proxy-group // containing the matched proxies' display names. // Returns one error per rule with an invalid match.name-pattern; other rules // still run. func buildProxyGroups(finalConfig map[string]interface{}, rules []ProxyGroupRule, proxies []ProxyRef) []error { var errs []error for _, rule := range rules { matched, err := matchProxies(proxies, rule.Match) if err != nil { errs = append(errs, fmt.Errorf("proxy-group '%s': %w", rule.Name, err)) continue } // Multiple ProxyRefs (e.g. each subscription's own default // selector) can share a DisplayName (e.g. once folded into a // combined "Proxy Selection" group) — dedupe so it's not listed // more than once. seen := make(map[string]bool, len(matched)) names := make([]interface{}, 0, len(matched)) for _, p := range matched { if seen[p.DisplayName] { continue } seen[p.DisplayName] = true names = append(names, p.DisplayName) } if len(matched) == 0 { fmt.Printf("ℹ️ ssm: proxy-group '%s' matched 0 proxies\n", rule.Name) } group := map[string]interface{}{ "name": rule.Name, "type": defaultString(rule.Type, "select"), "proxies": names, } for k, v := range rule.Extra { group[k] = v } appendProxyGroup(finalConfig, group) } return errs } func defaultString(v, fallback string) string { if v == "" { return fallback } return v } func appendProxyGroup(finalConfig map[string]interface{}, group map[string]interface{}) { existing, _ := finalConfig["proxy-groups"].([]interface{}) finalConfig["proxy-groups"] = append(existing, group) }