Skip to content

Commit

Permalink
Add feature flags from environment variable (#722)
Browse files Browse the repository at this point in the history
* Add featuretoggles package

* Change featuretoggles to experimental package

* Update folder.golden.txt

---------

Co-authored-by: Giuseppe Guerra <[email protected]>
  • Loading branch information
oshirohugo and xnyo authored Aug 28, 2023
1 parent 976bbdf commit d4c32f3
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 18 deletions.
47 changes: 47 additions & 0 deletions experimental/featuretoggles/featuretoggles.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package featuretoggles

import (
"os"
"strings"
)

// envFeatureTogglesEnable is the environment variable set by Grafana containing the list of enabled feature toggles.
const envFeatureTogglesEnable = "GF_INSTANCE_FEATURE_TOGGLES_ENABLE"

// FeatureToggles can check if feature toggles are enabled on the Grafana instance.
type FeatureToggles interface {
// IsEnabled returns true if the provided feature flag is set.
IsEnabled(flag string) bool
}

// featureToggles implements a FeatureToggles that returns true if a flag is present in the flags map.
type featureToggles struct {
// flags is a set-like map of feature flags that are enabled.
flags map[string]struct{}
}

// IsEnabled returns true if flag is contained in f.flags.
func (f featureToggles) IsEnabled(flag string) bool {
_, ok := f.flags[flag]
return ok
}

// newFeatureTogglesFromEnv returns a new featureToggles instance with its flags set from environment variables.
func newFeatureTogglesFromEnv() featureToggles {
return featureToggles{flags: flagsMapFromEnv()}
}

// flagsMapFromEnv returns a new set-like map[string]struct{}, where the keys are the space-separated names in
// the `envFeatureTogglesEnable` env var.
func flagsMapFromEnv() map[string]struct{} {
flags := strings.Split(os.Getenv(envFeatureTogglesEnable), ",")
r := make(map[string]struct{}, len(flags))
for _, flag := range flags {
r[flag] = struct{}{}
}
return r
}

// DefaultFeatureToggles is the default feature toggles implementation.
// It contains the same feature toggles as the Grafana instance where the plugin is running.
var DefaultFeatureToggles FeatureToggles = newFeatureTogglesFromEnv()
30 changes: 30 additions & 0 deletions experimental/featuretoggles/featuretoggles_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package featuretoggles

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestEnvFeatureToggles(t *testing.T) {
t.Run("should work when flag is provided", func(t *testing.T) {
t.Setenv(envFeatureTogglesEnable, "")
flags := newFeatureTogglesFromEnv()
require.False(t, flags.IsEnabled("abc"))
})

t.Run("should work when single flag is provided", func(t *testing.T) {
t.Setenv(envFeatureTogglesEnable, "abc")
flags := newFeatureTogglesFromEnv()
require.True(t, flags.IsEnabled("abc"))
require.False(t, flags.IsEnabled("def"))
})

t.Run("should work when multiple flags are provided", func(t *testing.T) {
t.Setenv(envFeatureTogglesEnable, "abc,def")
flags := newFeatureTogglesFromEnv()
require.True(t, flags.IsEnabled("abc"))
require.True(t, flags.IsEnabled("def"))
require.False(t, flags.IsEnabled("ghi"))
})
}
36 changes: 18 additions & 18 deletions experimental/testdata/folder.golden.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,24 @@ Frame[0] {
"pathSeparator": "/"
}
Name:
Dimensions: 2 Fields by 17 Rows
+----------------------+------------------+
| Name: name | Name: media-type |
| Labels: | Labels: |
| Type: []string | Type: []string |
+----------------------+------------------+
| README.md | |
| actions | directory |
| authclient | directory |
| datasourcetest | directory |
| e2e | directory |
| fileinfo.go | |
| fileinfo_test.go | |
| frame_sorter.go | |
| frame_sorter_test.go | |
| ... | ... |
+----------------------+------------------+
Dimensions: 2 Fields by 18 Rows
+------------------+------------------+
| Name: name | Name: media-type |
| Labels: | Labels: |
| Type: []string | Type: []string |
+------------------+------------------+
| README.md | |
| actions | directory |
| authclient | directory |
| datasourcetest | directory |
| e2e | directory |
| featuretoggles | directory |
| fileinfo.go | |
| fileinfo_test.go | |
| frame_sorter.go | |
| ... | ... |
+------------------+------------------+


====== TEST DATA RESPONSE (arrow base64) ======
FRAME=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
FRAME=QVJST1cxAAD/////yAEAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEEAAoADAAAAAgABAAKAAAACAAAALgAAAADAAAATAAAACgAAAAEAAAAwP7//wgAAAAMAAAAAAAAAAAAAAAFAAAAcmVmSWQAAADg/v//CAAAAAwAAAAAAAAAAAAAAAQAAABuYW1lAAAAAAD///8IAAAAUAAAAEQAAAB7InR5cGUiOiJkaXJlY3RvcnktbGlzdGluZyIsInR5cGVWZXJzaW9uIjpbMCwwXSwicGF0aFNlcGFyYXRvciI6Ii8ifQAAAAAEAAAAbWV0YQAAAAACAAAAeAAAAAQAAACi////FAAAADwAAAA8AAAAAAAABTgAAAABAAAABAAAAJD///8IAAAAEAAAAAYAAABzdHJpbmcAAAYAAAB0c3R5cGUAAAAAAACI////CgAAAG1lZGlhLXR5cGUAAAAAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAASAAAAAAAAAVEAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAYAAABzdHJpbmcAAAYAAAB0c3R5cGUAAAAAAAAEAAQABAAAAAQAAABuYW1lAAAAAP/////YAAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAA8AEAAAAAAAAUAAAAAAAAAwQACgAYAAwACAAEAAoAAAAUAAAAeAAAABIAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMAAAAAAAAAFAAAAAAAAAA7gAAAAAAAABAAQAAAAAAAAAAAAAAAAAAQAEAAAAAAABMAAAAAAAAAJABAAAAAAAAWgAAAAAAAAAAAAAAAgAAABIAAAAAAAAAAAAAAAAAAAASAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAQAAAAGgAAACgAAAArAAAAOQAAAEQAAABUAAAAYwAAAHcAAACRAAAAsAAAALsAAADBAAAAxQAAANgAAADmAAAA7gAAAAAAAABSRUFETUUubWRhY3Rpb25zYXV0aGNsaWVudGRhdGFzb3VyY2V0ZXN0ZTJlZmVhdHVyZXRvZ2dsZXNmaWxlaW5mby5nb2ZpbGVpbmZvX3Rlc3QuZ29mcmFtZV9zb3J0ZXIuZ29mcmFtZV9zb3J0ZXJfdGVzdC5nb2dvbGRlbl9yZXNwb25zZV9jaGVja2VyLmdvZ29sZGVuX3Jlc3BvbnNlX2NoZWNrZXJfdGVzdC5nb2h0dHBfbG9nZ2VybWFjcm9zbW9ja29hdXRodG9rZW5yZXRyaWV2ZXJyZXN0X2NsaWVudC5nb3Rlc3RkYXRhAAAAAAAAAAAAAAkAAAASAAAAGwAAACQAAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAANgAAAD8AAABIAAAAUQAAAFEAAABaAAAAAAAAAGRpcmVjdG9yeWRpcmVjdG9yeWRpcmVjdG9yeWRpcmVjdG9yeWRpcmVjdG9yeWRpcmVjdG9yeWRpcmVjdG9yeWRpcmVjdG9yeWRpcmVjdG9yeWRpcmVjdG9yeQAAAAAAABAAAAAMABQAEgAMAAgABAAMAAAAEAAAACwAAAA8AAAAAAAEAAEAAADYAQAAAAAAAOAAAAAAAAAA8AEAAAAAAAAAAAAAAAAAAAAAAAAAAAoADAAAAAgABAAKAAAACAAAALgAAAADAAAATAAAACgAAAAEAAAAwP7//wgAAAAMAAAAAAAAAAAAAAAFAAAAcmVmSWQAAADg/v//CAAAAAwAAAAAAAAAAAAAAAQAAABuYW1lAAAAAAD///8IAAAAUAAAAEQAAAB7InR5cGUiOiJkaXJlY3RvcnktbGlzdGluZyIsInR5cGVWZXJzaW9uIjpbMCwwXSwicGF0aFNlcGFyYXRvciI6Ii8ifQAAAAAEAAAAbWV0YQAAAAACAAAAeAAAAAQAAACi////FAAAADwAAAA8AAAAAAAABTgAAAABAAAABAAAAJD///8IAAAAEAAAAAYAAABzdHJpbmcAAAYAAAB0c3R5cGUAAAAAAACI////CgAAAG1lZGlhLXR5cGUAAAAAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAASAAAAAAAAAVEAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAYAAABzdHJpbmcAAAYAAAB0c3R5cGUAAAAAAAAEAAQABAAAAAQAAABuYW1lAAAAAPgBAABBUlJPVzE=

0 comments on commit d4c32f3

Please sign in to comment.