diff --git a/conf/defaults.ini b/conf/defaults.ini index 492151a87f2..978b650bdc3 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -133,7 +133,7 @@ url = # Set to true or false to enable or disable high availability mode. # When it's set to false some functions will be simplified and only run in-process # instead of relying on the database. -# +# # Only set it to false if you run only a single instance of Grafana. high_availability = true @@ -1928,6 +1928,15 @@ enable = # feature1 = true # feature2 = false +[feature_toggles.openfeature] +# This is EXPERIMENTAL. Please, do not use this section +provider = static + +[feature_toggles.openfeature.context] +# This is EXPERIMENTAL. Please, do not use this section +# instance = "grafana" +# version = 11.0.0 + [date_formats] # For information on what formatting patterns that are supported https://momentjs.com/docs/#/displaying/ diff --git a/go.mod b/go.mod index 89f3e71923c..b6e8a81dee8 100644 --- a/go.mod +++ b/go.mod @@ -551,12 +551,19 @@ require ( sigs.k8s.io/yaml v1.4.0 // indirect ) +require ( + github.com/open-feature/go-sdk v1.14.1 // @grafana/grafana-backend-group + github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.3 // @grafana/grafana-backend-group +) + require ( github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.49.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 // indirect + github.com/bluele/gcache v0.0.2 // indirect github.com/envoyproxy/go-control-plane/envoy v1.32.3 // indirect github.com/onsi/ginkgo/v2 v2.22.0 // indirect github.com/onsi/gomega v1.36.1 // indirect + github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.5 // indirect ) // Use fork of crewjam/saml with fixes for some issues until changes get merged into upstream diff --git a/go.sum b/go.sum index 265750417c2..7a1dcc578e9 100644 --- a/go.sum +++ b/go.sum @@ -939,6 +939,8 @@ github.com/blevesearch/zapx/v15 v15.3.16 h1:Ct3rv7FUJPfPk99TI/OofdC+Kpb4IdyfdMH4 github.com/blevesearch/zapx/v15 v15.3.16/go.mod h1:Turk/TNRKj9es7ZpKK95PS7f6D44Y7fAFy8F4LXQtGg= github.com/blevesearch/zapx/v16 v16.1.8 h1:Bxzpw6YQpFs7UjoCV1+RvDw6fmAT2GZxldwX8b3wVBM= github.com/blevesearch/zapx/v16 v16.1.8/go.mod h1:JqQlOqlRVaYDkpLIl3JnKql8u4zKTNlVEa3nLsi0Gn8= +github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw= +github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0= github.com/blugelabs/bluge v0.2.2 h1:gat8CqE6P6tOgeX30XGLOVNTC26cpM2RWVcreXWtYcM= github.com/blugelabs/bluge v0.2.2/go.mod h1:am1LU9jS8dZgWkRzkGLQN3757EgMs3upWrU2fdN9foE= github.com/blugelabs/bluge_segment_api v0.2.0 h1:cCX1Y2y8v0LZ7+EEJ6gH7dW6TtVTW4RhG0vp3R+N2Lo= @@ -2053,6 +2055,12 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw= github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= +github.com/open-feature/go-sdk v1.14.1 h1:jcxjCIG5Up3XkgYwWN5Y/WWfc6XobOhqrIwjyDBsoQo= +github.com/open-feature/go-sdk v1.14.1/go.mod h1:t337k0VB/t/YxJ9S0prT30ISUHwYmUd/jhUZgFcOvGg= +github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.3 h1:6jpO63NCEZv4xunJj+aNlDuFVuRkVBPMcIuxvFPYRWQ= +github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.3/go.mod h1:dPUHjAIFzg+ci/wt6XxlNiiMkOh5Yw4SGyeRY0AFT0g= +github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.5 h1:ZdqlGnNwhWf3luhBQlIpbglvcCzjkcuEgOEhYhr5Emc= +github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.5/go.mod h1:jrD4UG3ZCzuwImKHlyuIN2iWeYjlOX5+zJ/sX45efuE= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= diff --git a/go.work.sum b/go.work.sum index 67f94824134..d4cac4ef5d7 100644 --- a/go.work.sum +++ b/go.work.sum @@ -625,6 +625,8 @@ github.com/blevesearch/snowball v0.6.1 h1:cDYjn/NCH+wwt2UdehaLpr2e4BwLIjN4V/TdLs github.com/blevesearch/snowball v0.6.1/go.mod h1:ZF0IBg5vgpeoUhnMza2v0A/z8m1cWPlwhke08LpNusg= github.com/blevesearch/stempel v0.2.0 h1:CYzVPaScODMvgE9o+kf6D4RJ/VRomyi9uHF+PtB+Afc= github.com/blevesearch/stempel v0.2.0/go.mod h1:wjeTHqQv+nQdbPuJ/YcvOjTInA2EIc6Ks1FoSUzSLvc= +github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw= +github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs= github.com/bradleyjkemp/cupaloy/v2 v2.6.0 h1:knToPYa2xtfg42U3I6punFEjaGFKWQRXJwj0JTv4mTs= @@ -700,6 +702,12 @@ github.com/crewjam/httperr v0.2.0 h1:b2BfXR8U3AlIHwNeFFvZ+BV1LFvKLlzMjzaTnZMybNo github.com/crewjam/httperr v0.2.0/go.mod h1:Jlz+Sg/XqBQhyMjdDiC+GNNRzZTD7x39Gu3pglZ5oH4= github.com/cristalhq/hedgedhttp v0.9.1 h1:g68L9cf8uUyQKQJwciD0A1Vgbsz+QgCjuB1I8FAsCDs= github.com/cristalhq/hedgedhttp v0.9.1/go.mod h1:XkqWU6qVMutbhW68NnzjWrGtH8NUx1UfYqGYtHVKIsI= +github.com/cucumber/gherkin/go/v26 v26.2.0 h1:EgIjePLWiPeslwIWmNQ3XHcypPsWAHoMCz/YEBKP4GI= +github.com/cucumber/gherkin/go/v26 v26.2.0/go.mod h1:t2GAPnB8maCT4lkHL99BDCVNzCh1d7dBhCLt150Nr/0= +github.com/cucumber/godog v0.15.0 h1:51AL8lBXF3f0cyA5CV4TnJFCTHpgiy+1x1Hb3TtZUmo= +github.com/cucumber/godog v0.15.0/go.mod h1:FX3rzIDybWABU4kuIXLZ/qtqEe1Ac5RdXmqvACJOces= +github.com/cucumber/messages/go/v21 v21.0.1 h1:wzA0LxwjlWQYZd32VTlAVDTkW6inOFmSM+RuOwHZiMI= +github.com/cucumber/messages/go/v21 v21.0.1/go.mod h1:zheH/2HS9JLVFukdrsPWoPdmUtmYQAQPLk7w5vWsk5s= github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07 h1:UHFGPvSxX4C4YBApSPvmUfL8tTvWLj2ryqvT9K4Jcuk= github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f h1:7uSNgsgcarNk4oiN/nNkO0J7KAjlsF5Yv5Gf/tFdHas= github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4 h1:CVAqftqbj+exlab+8KJQrE+kNIVlQfJt58j4GxCMF1s= @@ -924,6 +932,8 @@ github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1 github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= github.com/hamba/avro/v2 v2.27.0 h1:IAM4lQ0VzUIKBuo4qlAiLKfqALSrFC+zi1iseTtbBKU= github.com/hamba/avro/v2 v2.27.0/go.mod h1:jN209lopfllfrz7IGoZErlDz+AyUJ3vrBePQFZwYf5I= +github.com/hashicorp/go-memdb v1.3.4 h1:XSL3NR682X/cVk2IeV0d70N4DZ9ljI885xAEU8IoK3c= +github.com/hashicorp/go-memdb v1.3.4/go.mod h1:uBTr1oQbtuMgd1SSGoR8YV27eT3sBHbYiNm53bMpgSg= github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-msgpack/v2 v2.1.1 h1:xQEY9yB2wnHitoSzk/B9UjXWRQ67QKu5AOm8aFp8N3I= github.com/hashicorp/go-msgpack/v2 v2.1.1/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4= @@ -1080,6 +1090,8 @@ github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8X github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8= github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= +github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.5 h1:ZdqlGnNwhWf3luhBQlIpbglvcCzjkcuEgOEhYhr5Emc= +github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.5/go.mod h1:jrD4UG3ZCzuwImKHlyuIN2iWeYjlOX5+zJ/sX45efuE= github.com/open-telemetry/opentelemetry-collector-contrib/exporter/kafkaexporter v0.102.0 h1:R70PpK14trQfL/Vj5oAiGRqX09s2gOWuf6t1Ae5fevQ= github.com/open-telemetry/opentelemetry-collector-contrib/exporter/kafkaexporter v0.102.0/go.mod h1:xmy/yFFmB1Epy+czrYMbA+4xeOKvhFqNqYWU6qINeis= github.com/open-telemetry/opentelemetry-collector-contrib/exporter/zipkinexporter v0.102.0 h1:N3vWsp3xealy4AX8TovfHG5EKi/k7z+F/8LFP4SVAgo= diff --git a/pkg/server/wire.go b/pkg/server/wire.go index 5bbd477bb2d..82b7e891669 100644 --- a/pkg/server/wire.go +++ b/pkg/server/wire.go @@ -301,6 +301,7 @@ var wireBasicSet = wire.NewSet( expr.ProvideService, featuremgmt.ProvideManagerService, featuremgmt.ProvideToggles, + featuremgmt.ProvideOpenFeatureService, dashboardservice.ProvideDashboardServiceImpl, wire.Bind(new(dashboards.PermissionsRegistrationService), new(*dashboardservice.DashboardServiceImpl)), dashboardservice.ProvideDashboardService, diff --git a/pkg/server/wireexts_oss.go b/pkg/server/wireexts_oss.go index 8f10bfd32e3..75e6f6842fb 100644 --- a/pkg/server/wireexts_oss.go +++ b/pkg/server/wireexts_oss.go @@ -147,6 +147,7 @@ var wireExtsBaseCLISet = wire.NewSet( metrics.WireSet, featuremgmt.ProvideManagerService, featuremgmt.ProvideToggles, + featuremgmt.ProvideOpenFeatureService, hooks.ProvideService, setting.ProvideProvider, wire.Bind(new(setting.Provider), new(*setting.OSSImpl)), licensing.ProvideService, wire.Bind(new(licensing.Licensing), new(*licensing.OSSLicensingService)), diff --git a/pkg/services/featuremgmt/goff_provider.go b/pkg/services/featuremgmt/goff_provider.go new file mode 100644 index 00000000000..c9ec290d870 --- /dev/null +++ b/pkg/services/featuremgmt/goff_provider.go @@ -0,0 +1,21 @@ +package featuremgmt + +import ( + "net/http" + "time" + + gofeatureflag "github.com/open-feature/go-sdk-contrib/providers/go-feature-flag/pkg" + "github.com/open-feature/go-sdk/openfeature" +) + +func newGOFFProvider(url string) (openfeature.FeatureProvider, error) { + options := gofeatureflag.ProviderOptions{ + Endpoint: url, + // consider using github.com/grafana/grafana/pkg/infra/httpclient/provider.go + HTTPClient: &http.Client{ + Timeout: 10 * time.Second, + }, + } + provider, err := gofeatureflag.NewProvider(options) + return provider, err +} diff --git a/pkg/services/featuremgmt/openfeature.go b/pkg/services/featuremgmt/openfeature.go new file mode 100644 index 00000000000..123fb1287b5 --- /dev/null +++ b/pkg/services/featuremgmt/openfeature.go @@ -0,0 +1,71 @@ +package featuremgmt + +import ( + "fmt" + + "github.com/grafana/grafana/pkg/setting" + "github.com/open-feature/go-sdk/openfeature" +) + +const ( + staticProviderType = "static" + goffProviderType = "goff" + + configSectionName = "feature_toggles.openfeature" + contextSectionName = "feature_toggles.openfeature.context" +) + +type OpenFeatureService struct { + provider openfeature.FeatureProvider + Client openfeature.IClient +} + +func ProvideOpenFeatureService(cfg *setting.Cfg) (*OpenFeatureService, error) { + conf := cfg.Raw.Section(configSectionName) + provType := conf.Key("provider").MustString(staticProviderType) + url := conf.Key("url").MustString("") + key := conf.Key("targetingKey").MustString(cfg.AppURL) + + var provider openfeature.FeatureProvider + var err error + if provType == goffProviderType { + provider, err = newGOFFProvider(url) + } else { + provider, err = newStaticProvider(cfg) + } + + if err != nil { + return nil, fmt.Errorf("failed to create %s feature provider: %w", provType, err) + } + + if err := openfeature.SetProviderAndWait(provider); err != nil { + return nil, fmt.Errorf("failed to set global %s feature provider: %w", provType, err) + } + + attrs := ctxAttrs(cfg) + openfeature.SetEvaluationContext(openfeature.NewEvaluationContext(key, attrs)) + + client := openfeature.NewClient("grafana-openfeature-client") + + return &OpenFeatureService{ + provider: provider, + Client: client, + }, nil +} + +// ctxAttrs uses config.ini [feature_toggles.openfeature.context] section to build the eval context attributes +func ctxAttrs(cfg *setting.Cfg) map[string]any { + ctxConf := cfg.Raw.Section(contextSectionName) + + attrs := map[string]any{} + for _, key := range ctxConf.KeyStrings() { + attrs[key] = ctxConf.Key(key).String() + } + + // Some default attributes + if _, ok := attrs["grafana_version"]; !ok { + attrs["grafana_version"] = setting.BuildVersion + } + + return attrs +} diff --git a/pkg/services/featuremgmt/openfeature_test.go b/pkg/services/featuremgmt/openfeature_test.go new file mode 100644 index 00000000000..919c3592e6e --- /dev/null +++ b/pkg/services/featuremgmt/openfeature_test.go @@ -0,0 +1,113 @@ +package featuremgmt + +import ( + "testing" + + "github.com/grafana/grafana/pkg/setting" + + gofeatureflag "github.com/open-feature/go-sdk-contrib/providers/go-feature-flag/pkg" + "github.com/open-feature/go-sdk/openfeature/memprovider" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestProvideOpenFeatureManager(t *testing.T) { + testCases := []struct { + name string + cfg string + expectedProvider string + }{ + { + name: "static provider", + expectedProvider: staticProviderType, + }, + { + name: "goff provider", + cfg: ` +[feature_toggles.openfeature] +provider = goff +url = http://localhost:1031 +targetingKey = grafana +`, + expectedProvider: goffProviderType, + }, + { + name: "invalid provider", + cfg: ` +[feature_toggles.openfeature] +provider = some_provider +`, + expectedProvider: staticProviderType, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + cfg := setting.NewCfg() + if tc.cfg != "" { + err := cfg.Raw.Append([]byte(tc.cfg)) + require.NoError(t, err) + } + + p, err := ProvideOpenFeatureService(cfg) + require.NoError(t, err) + + if tc.expectedProvider == goffProviderType { + _, ok := p.provider.(*gofeatureflag.Provider) + assert.True(t, ok, "expected provider to be of type goff.Provider") + } else { + _, ok := p.provider.(memprovider.InMemoryProvider) + assert.True(t, ok, "expected provider to be of type memprovider.InMemoryProvider") + } + }) + } +} + +func Test_CtxAttrs(t *testing.T) { + testCases := []struct { + name string + conf string + expected map[string]any + }{ + { + name: "empty config - only default attributes should be present", + expected: map[string]any{ + "grafana_version": "", + }, + }, + { + name: "config with some attributes", + conf: ` +[feature_toggles.openfeature.context] +foo = bar +baz = qux +quux = corge`, + expected: map[string]any{ + "foo": "bar", + "baz": "qux", + "quux": "corge", + "grafana_version": "", + }, + }, + { + name: "config with an attribute that overrides a default one", + conf: ` +[feature_toggles.openfeature.context] +grafana_version = 10.0.0 +foo = bar`, + expected: map[string]any{ + "grafana_version": "10.0.0", + "foo": "bar", + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + cfg, err := setting.NewCfgFromBytes([]byte(tc.conf)) + require.NoError(t, err) + + assert.Equal(t, tc.expected, ctxAttrs(cfg)) + }) + } +} diff --git a/pkg/services/featuremgmt/static_provider.go b/pkg/services/featuremgmt/static_provider.go new file mode 100644 index 00000000000..03ae93a8086 --- /dev/null +++ b/pkg/services/featuremgmt/static_provider.go @@ -0,0 +1,49 @@ +package featuremgmt + +import ( + "fmt" + + "github.com/grafana/grafana/pkg/setting" + "github.com/open-feature/go-sdk/openfeature" + "github.com/open-feature/go-sdk/openfeature/memprovider" +) + +func newStaticProvider(cfg *setting.Cfg) (openfeature.FeatureProvider, error) { + confFlags, err := setting.ReadFeatureTogglesFromInitFile(cfg.Raw.Section("feature_toggles")) + if err != nil { + return nil, fmt.Errorf("failed to read feature toggles from config: %w", err) + } + + flags := make(map[string]memprovider.InMemoryFlag, len(standardFeatureFlags)) + + // Add flags from config.ini file + for name, value := range confFlags { + flags[name] = createInMemoryFlag(name, value) + } + + // Add standard flags + for _, flag := range standardFeatureFlags { + if _, exists := flags[flag.Name]; !exists { + enabled := flag.Expression == "true" + flags[flag.Name] = createInMemoryFlag(flag.Name, enabled) + } + } + + return memprovider.NewInMemoryProvider(flags), nil +} + +func createInMemoryFlag(name string, enabled bool) memprovider.InMemoryFlag { + variant := "disabled" + if enabled { + variant = "enabled" + } + + return memprovider.InMemoryFlag{ + Key: name, + DefaultVariant: variant, + Variants: map[string]interface{}{ + "enabled": true, + "disabled": false, + }, + } +} diff --git a/pkg/services/featuremgmt/static_provider_test.go b/pkg/services/featuremgmt/static_provider_test.go new file mode 100644 index 00000000000..97ce98fa656 --- /dev/null +++ b/pkg/services/featuremgmt/static_provider_test.go @@ -0,0 +1,58 @@ +package featuremgmt + +import ( + "context" + "testing" + + "github.com/grafana/grafana/pkg/setting" + + "github.com/open-feature/go-sdk/openfeature" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_StaticProvider(t *testing.T) { + ctx := context.Background() + evalCtx := openfeature.NewEvaluationContext("grafana", nil) + + stFeat := standardFeatureFlags[0] + stFeatName := stFeat.Name + stFeatValue := stFeat.Expression == "true" + + t.Run("empty config loads standard flags", func(t *testing.T) { + p := provider(t, []byte(``)) + // Check for one of the standard flags + feat, err := p.Client.BooleanValueDetails(ctx, stFeatName, !stFeatValue, evalCtx) + assert.NoError(t, err) + assert.True(t, stFeatValue == feat.Value) + }) + + t.Run("featureOne does not exist in standard flags but should be loaded", func(t *testing.T) { + conf := []byte(` +[feature_toggles] +featureOne = true +`) + p := provider(t, conf) + feat, err := p.Client.BooleanValueDetails(ctx, "featureOne", false, evalCtx) + assert.NoError(t, err) + assert.True(t, feat.Value) + }) + + t.Run("missing feature should return default evaluation value and an error", func(t *testing.T) { + p := provider(t, []byte(``)) + missingFeature, err := p.Client.BooleanValueDetails(ctx, "missingFeature", true, evalCtx) + assert.Error(t, err) + assert.True(t, missingFeature.Value) + assert.Equal(t, openfeature.ErrorCode("FLAG_NOT_FOUND"), missingFeature.ErrorCode) + }) +} + +func provider(t *testing.T, conf []byte) *OpenFeatureService { + t.Helper() + cfg, err := setting.NewCfgFromBytes(conf) + require.NoError(t, err) + + p, err := ProvideOpenFeatureService(cfg) + require.NoError(t, err) + return p +} diff --git a/pkg/storage/unified/apistore/go.mod b/pkg/storage/unified/apistore/go.mod index 02ddaeaa0b3..9c732c09acd 100644 --- a/pkg/storage/unified/apistore/go.mod +++ b/pkg/storage/unified/apistore/go.mod @@ -117,6 +117,7 @@ require ( github.com/blevesearch/zapx/v14 v14.3.10 // indirect github.com/blevesearch/zapx/v15 v15.3.16 // indirect github.com/blevesearch/zapx/v16 v16.1.8 // indirect + github.com/bluele/gcache v0.0.2 // indirect github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect github.com/bufbuild/protocompile v0.4.0 // indirect github.com/buger/jsonparser v1.1.1 // indirect @@ -297,6 +298,9 @@ require ( github.com/oklog/ulid v1.3.1 // indirect github.com/oklog/ulid/v2 v2.1.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/open-feature/go-sdk v1.14.1 // indirect + github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.3 // indirect + github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.5 // indirect github.com/openfga/api/proto v0.0.0-20250127102726-f9709139a369 // indirect github.com/openfga/language/pkg/go v0.2.0-beta.2.0.20250121233318-0eae96a39570 // indirect github.com/openfga/openfga v1.8.6 // indirect diff --git a/pkg/storage/unified/apistore/go.sum b/pkg/storage/unified/apistore/go.sum index a38b7f3186f..85811800a65 100644 --- a/pkg/storage/unified/apistore/go.sum +++ b/pkg/storage/unified/apistore/go.sum @@ -828,6 +828,8 @@ github.com/blevesearch/zapx/v15 v15.3.16 h1:Ct3rv7FUJPfPk99TI/OofdC+Kpb4IdyfdMH4 github.com/blevesearch/zapx/v15 v15.3.16/go.mod h1:Turk/TNRKj9es7ZpKK95PS7f6D44Y7fAFy8F4LXQtGg= github.com/blevesearch/zapx/v16 v16.1.8 h1:Bxzpw6YQpFs7UjoCV1+RvDw6fmAT2GZxldwX8b3wVBM= github.com/blevesearch/zapx/v16 v16.1.8/go.mod h1:JqQlOqlRVaYDkpLIl3JnKql8u4zKTNlVEa3nLsi0Gn8= +github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw= +github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= @@ -1562,6 +1564,12 @@ github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw= github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= +github.com/open-feature/go-sdk v1.14.1 h1:jcxjCIG5Up3XkgYwWN5Y/WWfc6XobOhqrIwjyDBsoQo= +github.com/open-feature/go-sdk v1.14.1/go.mod h1:t337k0VB/t/YxJ9S0prT30ISUHwYmUd/jhUZgFcOvGg= +github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.3 h1:6jpO63NCEZv4xunJj+aNlDuFVuRkVBPMcIuxvFPYRWQ= +github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.3/go.mod h1:dPUHjAIFzg+ci/wt6XxlNiiMkOh5Yw4SGyeRY0AFT0g= +github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.5 h1:ZdqlGnNwhWf3luhBQlIpbglvcCzjkcuEgOEhYhr5Emc= +github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.5/go.mod h1:jrD4UG3ZCzuwImKHlyuIN2iWeYjlOX5+zJ/sX45efuE= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= diff --git a/pkg/storage/unified/resource/go.mod b/pkg/storage/unified/resource/go.mod index 5bd606b0bea..7205ba6e55a 100644 --- a/pkg/storage/unified/resource/go.mod +++ b/pkg/storage/unified/resource/go.mod @@ -80,6 +80,7 @@ require ( github.com/aws/smithy-go v1.20.3 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect + github.com/bluele/gcache v0.0.2 // indirect github.com/bufbuild/protocompile v0.4.0 // indirect github.com/bwmarrin/snowflake v0.3.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect @@ -186,6 +187,9 @@ require ( github.com/oklog/run v1.1.0 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/open-feature/go-sdk v1.14.1 // indirect + github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.3 // indirect + github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.5 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect diff --git a/pkg/storage/unified/resource/go.sum b/pkg/storage/unified/resource/go.sum index 3aede8a23e6..2fcb42eb4e9 100644 --- a/pkg/storage/unified/resource/go.sum +++ b/pkg/storage/unified/resource/go.sum @@ -764,6 +764,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw= +github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= @@ -1383,6 +1385,12 @@ github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/open-feature/go-sdk v1.14.1 h1:jcxjCIG5Up3XkgYwWN5Y/WWfc6XobOhqrIwjyDBsoQo= +github.com/open-feature/go-sdk v1.14.1/go.mod h1:t337k0VB/t/YxJ9S0prT30ISUHwYmUd/jhUZgFcOvGg= +github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.3 h1:6jpO63NCEZv4xunJj+aNlDuFVuRkVBPMcIuxvFPYRWQ= +github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.3/go.mod h1:dPUHjAIFzg+ci/wt6XxlNiiMkOh5Yw4SGyeRY0AFT0g= +github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.5 h1:ZdqlGnNwhWf3luhBQlIpbglvcCzjkcuEgOEhYhr5Emc= +github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.5/go.mod h1:jrD4UG3ZCzuwImKHlyuIN2iWeYjlOX5+zJ/sX45efuE= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=