package automation import ( "fmt" "gopkg.in/yaml.v3" "gitea.epss.net.cn/klesh/ss/internal/yamlutil" ) // ParseConfig converts the raw (already YAML-decoded) `ssm:` block value — // pulled out of the generic map produced by loading core-config.yaml — into // a strongly-typed Config, by round-tripping it through YAML. func ParseConfig(raw interface{}) (*Config, error) { data, err := yaml.Marshal(raw) if err != nil { return nil, fmt.Errorf("failed to marshal ssm config: %w", err) } var cfg Config if err := yamlutil.Unmarshal(data, &cfg); err != nil { return nil, fmt.Errorf("failed to parse ssm config: %w", err) } return &cfg, nil } // Apply runs every ssm automation rule against finalConfig (the fully // merged generated config, with essential/DNS defaults already applied), // using proxies as the pool collected while merging active subscriptions. // Each rule/patch is independent: one failing doesn't stop the rest, and // all failures are returned as non-fatal errors for the caller to log. func Apply(finalConfig map[string]interface{}, cfg *Config, proxies []ProxyRef) []error { var errs []error buildProxyGroups(finalConfig, cfg.ProxyGroups, proxies) if rateErrs := buildRateFilterGroups(finalConfig, cfg.RateFilters, proxies); len(rateErrs) > 0 { errs = append(errs, rateErrs...) } for _, patch := range cfg.Patches { if err := applyPatch(finalConfig, patch); err != nil { errs = append(errs, fmt.Errorf("patch %q: %w", patch.Path, err)) } } return errs }