diff --git a/pkg/services/featuremgmt/openfeature.go b/pkg/services/featuremgmt/openfeature.go index 90aad955db1..234739ee59f 100644 --- a/pkg/services/featuremgmt/openfeature.go +++ b/pkg/services/featuremgmt/openfeature.go @@ -17,6 +17,48 @@ const ( featuresProviderAudience = "features.grafana.app" ) +// OpenFeatureConfig holds configuration for initializing OpenFeature +type OpenFeatureConfig struct { + // ProviderType is either "static" or "goff" + ProviderType string + // URL is the GOFF service URL (required for GOFF provider) + URL *url.URL + // HTTPClient is a pre-configured HTTP client (optional, used for GOFF provider) + HTTPClient *http.Client + // StaticFlags are the feature flags to use with static provider + StaticFlags map[string]bool + // TargetingKey is used for evaluation context + TargetingKey string + // ContextAttrs are additional attributes for evaluation context + ContextAttrs map[string]any +} + +// InitOpenFeature initializes OpenFeature with the provided configuration +func InitOpenFeature(config OpenFeatureConfig) error { + // For GOFF provider, ensure we have a URL + if config.ProviderType == setting.GOFFProviderType && (config.URL == nil || config.URL.String() == "") { + return fmt.Errorf("URL is required for GOFF provider") + } + + p, err := createProvider(config.ProviderType, config.URL, config.StaticFlags, config.HTTPClient) + if err != nil { + return err + } + + if err = openfeature.SetProviderAndWait(p); err != nil { + return fmt.Errorf("failed to set global feature provider: %s, %w", config.ProviderType, err) + } + + contextAttrs := make(map[string]any) + for k, v := range config.ContextAttrs { + contextAttrs[k] = v + } + openfeature.SetEvaluationContext(openfeature.NewEvaluationContext(config.TargetingKey, contextAttrs)) + + return nil +} + +// InitOpenFeatureWithCfg initializes OpenFeature from setting.Cfg func InitOpenFeatureWithCfg(cfg *setting.Cfg) error { confFlags, err := setting.ReadFeatureTogglesFromInitFile(cfg.Raw.Section("feature_toggles")) if err != nil { @@ -36,35 +78,19 @@ func InitOpenFeatureWithCfg(cfg *setting.Cfg) error { } } - err = initOpenFeature(cfg.OpenFeature.ProviderType, cfg.OpenFeature.URL, confFlags, httpcli) - if err != nil { - return fmt.Errorf("failed to initialize OpenFeature: %w", err) - } contextAttrs := make(map[string]any) for k, v := range cfg.OpenFeature.ContextAttrs { contextAttrs[k] = v } - openfeature.SetEvaluationContext(openfeature.NewEvaluationContext(cfg.OpenFeature.TargetingKey, contextAttrs)) - return nil -} - -func initOpenFeature( - providerType string, - u *url.URL, - staticFlags map[string]bool, - httpClient *http.Client, -) error { - p, err := createProvider(providerType, u, staticFlags, httpClient) - if err != nil { - return err - } - - if err := openfeature.SetProviderAndWait(p); err != nil { - return fmt.Errorf("failed to set global feature provider: %s, %w", providerType, err) - } - - return nil + return InitOpenFeature(OpenFeatureConfig{ + ProviderType: cfg.OpenFeature.ProviderType, + URL: cfg.OpenFeature.URL, + HTTPClient: httpcli, + StaticFlags: confFlags, + TargetingKey: cfg.OpenFeature.TargetingKey, + ContextAttrs: contextAttrs, + }) } func createProvider(