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 — subscription-provided proxy-groups already // merged in, essential/DNS defaults already applied), using proxies as the // pool collected while merging active subscriptions. proxy-groups rules run // first so filters rules can also scrub proxies out of the groups they // build. 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 errs = append(errs, buildProxyGroups(finalConfig, cfg.ProxyGroups, proxies)...) errs = append(errs, applyFilters(finalConfig, cfg.Filters, proxies)...) 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 }