|
8 | 8 | "strings" |
9 | 9 | "time" |
10 | 10 |
|
| 11 | + "github.com/splitio/go-split-commons/v9/dtos" |
11 | 12 | "github.com/splitio/go-toolkit/v5/logging" |
12 | 13 | "github.com/splitio/splitd/splitio/common/lang" |
13 | 14 | "github.com/splitio/splitd/splitio/link" |
@@ -122,21 +123,23 @@ func (l *Link) ToListenerOpts() (*link.ListenerOptions, error) { |
122 | 123 | } |
123 | 124 |
|
124 | 125 | type SDK struct { |
125 | | - Apikey string `yaml:"apikey"` |
126 | | - LabelsEnabled *bool `yaml:"labelsEnabled"` |
127 | | - StreamingEnabled *bool `yaml:"streamingEnabled"` |
128 | | - URLs URLs `yaml:"urls"` |
129 | | - FeatureFlags FeatureFlags `yaml:"featureFlags"` |
130 | | - Impressions Impressions `yaml:"impressions"` |
131 | | - Events Events `yaml:"events"` |
132 | | - FlagSetsFilter []string `yaml:"flagSetsFilter"` |
| 126 | + Apikey string `yaml:"apikey"` |
| 127 | + LabelsEnabled *bool `yaml:"labelsEnabled"` |
| 128 | + StreamingEnabled *bool `yaml:"streamingEnabled"` |
| 129 | + FallbackTreatment fallbackTreatmentInput `yaml:"fallbackTreatment"` |
| 130 | + URLs URLs `yaml:"urls"` |
| 131 | + FeatureFlags FeatureFlags `yaml:"featureFlags"` |
| 132 | + Impressions Impressions `yaml:"impressions"` |
| 133 | + Events Events `yaml:"events"` |
| 134 | + FlagSetsFilter []string `yaml:"flagSetsFilter"` |
133 | 135 | } |
134 | 136 |
|
135 | 137 | func (s *SDK) PopulateWithDefaults() { |
136 | 138 | cfg := sdkConf.DefaultConfig() |
137 | 139 | s.Apikey = apikeyPlaceHolder |
138 | 140 | s.LabelsEnabled = lang.Ref(cfg.LabelsEnabled) |
139 | 141 | s.StreamingEnabled = lang.Ref(cfg.StreamingEnabled) |
| 142 | + s.FallbackTreatment = fallbackTreatmentFromConfig(cfg.FallbackTreatment) |
140 | 143 | s.URLs.PopulateWithDefaults() |
141 | 144 | s.FeatureFlags.PopulateWithDefaults() |
142 | 145 | s.Impressions.PopulateWithDefaults() |
@@ -216,6 +219,11 @@ func (s *SDK) ToSDKConf() *sdkConf.Config { |
216 | 219 | if len(s.FlagSetsFilter) > 0 { |
217 | 220 | cfg.FlagSetsFilter = s.FlagSetsFilter |
218 | 221 | } |
| 222 | + if parsed, err := (&s.FallbackTreatment).toConfig(); err != nil { |
| 223 | + log.Printf("[splitd] fallbackTreatment: %v", err) |
| 224 | + } else if parsed != nil { |
| 225 | + cfg.FallbackTreatment = *parsed |
| 226 | + } |
219 | 227 | return cfg |
220 | 228 | } |
221 | 229 |
|
@@ -310,6 +318,113 @@ func (p *Profiling) PopulateWithDefaults() { |
310 | 318 | p.Port = 8888 |
311 | 319 | } |
312 | 320 |
|
| 321 | +// fallbackTreatmentFromConfig maps the SDK default config's FallbackTreatment into our input type. |
| 322 | +func fallbackTreatmentFromConfig(c dtos.FallbackTreatmentConfig) fallbackTreatmentInput { |
| 323 | + parsed := new(dtos.FallbackTreatmentConfig) |
| 324 | + *parsed = c |
| 325 | + return fallbackTreatmentInput{parsed: parsed} |
| 326 | +} |
| 327 | + |
| 328 | +type fallbackTreatmentEntry struct { |
| 329 | + Treatment *string `json:"treatment" yaml:"treatment"` |
| 330 | + Config *string `json:"config,omitempty" yaml:"config,omitempty"` |
| 331 | +} |
| 332 | + |
| 333 | +type fallbackTreatmentInput struct { |
| 334 | + parsed *dtos.FallbackTreatmentConfig |
| 335 | + raw string |
| 336 | +} |
| 337 | + |
| 338 | +func (f *fallbackTreatmentInput) UnmarshalYAML(value *yaml.Node) error { |
| 339 | + if value == nil { |
| 340 | + return nil |
| 341 | + } |
| 342 | + switch value.Kind { |
| 343 | + case yaml.ScalarNode: |
| 344 | + var s string |
| 345 | + if err := value.Decode(&s); err != nil { |
| 346 | + return err |
| 347 | + } |
| 348 | + f.parsed = nil |
| 349 | + f.raw = strings.TrimSpace(s) |
| 350 | + return nil |
| 351 | + case yaml.MappingNode: |
| 352 | + var m struct { |
| 353 | + Global *fallbackTreatmentEntry `yaml:"global_fallback_treatment"` |
| 354 | + ByFlag map[string]fallbackTreatmentEntry `yaml:"by_flag_fallback_treatment"` |
| 355 | + } |
| 356 | + if err := value.Decode(&m); err != nil { |
| 357 | + return err |
| 358 | + } |
| 359 | + out := dtos.FallbackTreatmentConfig{} |
| 360 | + if m.Global != nil && m.Global.Treatment != nil { |
| 361 | + out.GlobalFallbackTreatment = &dtos.FallbackTreatment{ |
| 362 | + Treatment: m.Global.Treatment, |
| 363 | + Config: m.Global.Config, |
| 364 | + } |
| 365 | + } |
| 366 | + if len(m.ByFlag) > 0 { |
| 367 | + out.ByFlagFallbackTreatment = make(map[string]dtos.FallbackTreatment) |
| 368 | + for name, v := range m.ByFlag { |
| 369 | + if v.Treatment != nil { |
| 370 | + out.ByFlagFallbackTreatment[name] = dtos.FallbackTreatment{ |
| 371 | + Treatment: v.Treatment, |
| 372 | + Config: v.Config, |
| 373 | + } |
| 374 | + } |
| 375 | + } |
| 376 | + } |
| 377 | + f.parsed = &out |
| 378 | + return nil |
| 379 | + } |
| 380 | + return nil |
| 381 | +} |
| 382 | + |
| 383 | +func (f *fallbackTreatmentInput) toConfig() (*dtos.FallbackTreatmentConfig, error) { |
| 384 | + if f == nil { |
| 385 | + return nil, nil |
| 386 | + } |
| 387 | + if f.raw != "" { |
| 388 | + return parseFallbackTreatmentJSON(f.raw) |
| 389 | + } |
| 390 | + if f.parsed != nil { |
| 391 | + return f.parsed, nil |
| 392 | + } |
| 393 | + return nil, nil |
| 394 | +} |
| 395 | + |
| 396 | +func parseFallbackTreatmentJSON(raw string) (*dtos.FallbackTreatmentConfig, error) { |
| 397 | + var wrapper struct { |
| 398 | + FallbackTreatment struct { |
| 399 | + GlobalFallbackTreatment *fallbackTreatmentEntry `json:"global_fallback_treatment"` |
| 400 | + ByFlagFallbackTreatment map[string]fallbackTreatmentEntry `json:"by_flag_fallback_treatment"` |
| 401 | + } `json:"fallback_treatment"` |
| 402 | + } |
| 403 | + if err := json.Unmarshal([]byte(raw), &wrapper); err != nil { |
| 404 | + return nil, fmt.Errorf("invalid JSON: %w", err) |
| 405 | + } |
| 406 | + out := dtos.FallbackTreatmentConfig{} |
| 407 | + inner := &wrapper.FallbackTreatment |
| 408 | + if inner.GlobalFallbackTreatment != nil && inner.GlobalFallbackTreatment.Treatment != nil { |
| 409 | + out.GlobalFallbackTreatment = &dtos.FallbackTreatment{ |
| 410 | + Treatment: inner.GlobalFallbackTreatment.Treatment, |
| 411 | + Config: inner.GlobalFallbackTreatment.Config, |
| 412 | + } |
| 413 | + } |
| 414 | + if len(inner.ByFlagFallbackTreatment) > 0 { |
| 415 | + out.ByFlagFallbackTreatment = make(map[string]dtos.FallbackTreatment) |
| 416 | + for name, v := range inner.ByFlagFallbackTreatment { |
| 417 | + if v.Treatment != nil { |
| 418 | + out.ByFlagFallbackTreatment[name] = dtos.FallbackTreatment{ |
| 419 | + Treatment: v.Treatment, |
| 420 | + Config: v.Config, |
| 421 | + } |
| 422 | + } |
| 423 | + } |
| 424 | + } |
| 425 | + return &out, nil |
| 426 | +} |
| 427 | + |
313 | 428 | func ReadConfig() (*Config, error) { |
314 | 429 | cfgFN := defaultConfigFN |
315 | 430 | if fromEnv := os.Getenv("SPLITD_CONF_FILE"); fromEnv != "" { |
|
0 commit comments