mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Feature Toggles: Validate if a GA toggle is enabled or not explicitly (#88277)
This commit is contained in:
parent
1be5c52a35
commit
c9271edfa1
@ -25,6 +25,7 @@ var (
|
|||||||
Owner: grafanaAsCodeSquad,
|
Owner: grafanaAsCodeSquad,
|
||||||
HideFromAdminPage: true,
|
HideFromAdminPage: true,
|
||||||
AllowSelfServe: false,
|
AllowSelfServe: false,
|
||||||
|
Expression: "false",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "live-service-web-worker",
|
Name: "live-service-web-worker",
|
||||||
@ -82,6 +83,7 @@ var (
|
|||||||
Stage: FeatureStageGeneralAvailability,
|
Stage: FeatureStageGeneralAvailability,
|
||||||
Owner: grafanaAsCodeSquad,
|
Owner: grafanaAsCodeSquad,
|
||||||
AllowSelfServe: true,
|
AllowSelfServe: true,
|
||||||
|
Expression: "false",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "storage",
|
Name: "storage",
|
||||||
@ -521,6 +523,7 @@ var (
|
|||||||
Stage: FeatureStageGeneralAvailability,
|
Stage: FeatureStageGeneralAvailability,
|
||||||
FrontendOnly: true,
|
FrontendOnly: true,
|
||||||
Owner: grafanaObservabilityTracesAndProfilingSquad,
|
Owner: grafanaObservabilityTracesAndProfilingSquad,
|
||||||
|
Expression: "false",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "metricsSummary",
|
Name: "metricsSummary",
|
||||||
@ -1026,6 +1029,7 @@ var (
|
|||||||
Stage: FeatureStageGeneralAvailability,
|
Stage: FeatureStageGeneralAvailability,
|
||||||
Owner: grafanaAlertingSquad,
|
Owner: grafanaAlertingSquad,
|
||||||
AllowSelfServe: false,
|
AllowSelfServe: false,
|
||||||
|
Expression: "false",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "newFolderPicker",
|
Name: "newFolderPicker",
|
||||||
@ -1259,6 +1263,7 @@ var (
|
|||||||
Stage: FeatureStageGeneralAvailability,
|
Stage: FeatureStageGeneralAvailability,
|
||||||
Owner: identityAccessTeam,
|
Owner: identityAccessTeam,
|
||||||
HideFromDocs: true,
|
HideFromDocs: true,
|
||||||
|
Expression: "false",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "alertingDisableSendAlertsExternal",
|
Name: "alertingDisableSendAlertsExternal",
|
||||||
|
@ -25,46 +25,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestFeatureToggleFiles(t *testing.T) {
|
func TestFeatureToggleFiles(t *testing.T) {
|
||||||
legacyNames := map[string]bool{
|
|
||||||
"live-service-web-worker": true,
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Run("check registry constraints", func(t *testing.T) {
|
t.Run("check registry constraints", func(t *testing.T) {
|
||||||
invalidNames := make([]string, 0)
|
verifyFlagsConfiguration(t)
|
||||||
|
|
||||||
// Check that all flags set in code are valid
|
|
||||||
for _, flag := range standardFeatureFlags {
|
|
||||||
if flag.Expression == "true" && !(flag.Stage == FeatureStageGeneralAvailability || flag.Stage == FeatureStageDeprecated) {
|
|
||||||
t.Errorf("only FeatureStageGeneralAvailability or FeatureStageDeprecated features can be enabled by default. See: %s", flag.Name)
|
|
||||||
}
|
|
||||||
if flag.RequiresDevMode && flag.Stage != FeatureStageExperimental {
|
|
||||||
t.Errorf("only alpha features can require dev mode. See: %s", flag.Name)
|
|
||||||
}
|
|
||||||
if flag.Stage == FeatureStageUnknown {
|
|
||||||
t.Errorf("standard toggles should not have an unknown state. See: %s", flag.Name)
|
|
||||||
}
|
|
||||||
if flag.Description != strings.TrimSpace(flag.Description) {
|
|
||||||
t.Errorf("flag Description should not start/end with spaces. See: %s", flag.Name)
|
|
||||||
}
|
|
||||||
if flag.Name != strings.TrimSpace(flag.Name) {
|
|
||||||
t.Errorf("flag Name should not start/end with spaces. See: %s", flag.Name)
|
|
||||||
}
|
|
||||||
if flag.AllowSelfServe && !(flag.Stage == FeatureStageGeneralAvailability || flag.Stage == FeatureStagePublicPreview || flag.Stage == FeatureStageDeprecated) {
|
|
||||||
t.Errorf("only allow self-serving GA, PublicPreview and Deprecated toggles")
|
|
||||||
}
|
|
||||||
if flag.Owner == "" {
|
|
||||||
t.Errorf("feature %s does not have an owner. please fill the FeatureFlag.Owner property", flag.Name)
|
|
||||||
}
|
|
||||||
// Check camel case names
|
|
||||||
if flag.Name != strcase.ToLowerCamel(flag.Name) && !legacyNames[flag.Name] {
|
|
||||||
invalidNames = append(invalidNames, flag.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure the names are valid
|
|
||||||
require.Empty(t, invalidNames, "%s feature names should be camel cased", invalidNames)
|
|
||||||
// acronyms can be configured as needed via `ConfigureAcronym` function from `./strcase/camel.go`
|
|
||||||
|
|
||||||
// Now that we know they are valid, update the json database
|
// Now that we know they are valid, update the json database
|
||||||
t.Run("update k8s resource list", func(t *testing.T) {
|
t.Run("update k8s resource list", func(t *testing.T) {
|
||||||
created := v1.NewTime(time.Now().UTC())
|
created := v1.NewTime(time.Now().UTC())
|
||||||
@ -180,6 +142,53 @@ func TestFeatureToggleFiles(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if all flags are configured properly
|
||||||
|
func verifyFlagsConfiguration(t *testing.T) {
|
||||||
|
legacyNames := map[string]bool{
|
||||||
|
"live-service-web-worker": true,
|
||||||
|
}
|
||||||
|
invalidNames := make([]string, 0)
|
||||||
|
|
||||||
|
// Check that all flags set in code are valid
|
||||||
|
for _, flag := range standardFeatureFlags {
|
||||||
|
if flag.Expression == "true" && !(flag.Stage == FeatureStageGeneralAvailability || flag.Stage == FeatureStageDeprecated) {
|
||||||
|
t.Errorf("only FeatureStageGeneralAvailability or FeatureStageDeprecated features can be enabled by default. See: %s", flag.Name)
|
||||||
|
}
|
||||||
|
if flag.RequiresDevMode && flag.Stage != FeatureStageExperimental {
|
||||||
|
t.Errorf("only alpha features can require dev mode. See: %s", flag.Name)
|
||||||
|
}
|
||||||
|
if flag.Stage == FeatureStageUnknown {
|
||||||
|
t.Errorf("standard toggles should not have an unknown state. See: %s", flag.Name)
|
||||||
|
}
|
||||||
|
if flag.Description != strings.TrimSpace(flag.Description) {
|
||||||
|
t.Errorf("flag Description should not start/end with spaces. See: %s", flag.Name)
|
||||||
|
}
|
||||||
|
if flag.Name != strings.TrimSpace(flag.Name) {
|
||||||
|
t.Errorf("flag Name should not start/end with spaces. See: %s", flag.Name)
|
||||||
|
}
|
||||||
|
if flag.AllowSelfServe && !(flag.Stage == FeatureStageGeneralAvailability || flag.Stage == FeatureStagePublicPreview || flag.Stage == FeatureStageDeprecated) {
|
||||||
|
t.Errorf("only allow self-serving GA, PublicPreview and Deprecated toggles")
|
||||||
|
}
|
||||||
|
if flag.Owner == "" {
|
||||||
|
t.Errorf("feature %s does not have an owner. please fill the FeatureFlag.Owner property", flag.Name)
|
||||||
|
}
|
||||||
|
if flag.Stage == FeatureStageGeneralAvailability && flag.Expression == "" {
|
||||||
|
t.Errorf("GA features must be explicitly enabled or disabled, please add the `Expression` property for %s", flag.Name)
|
||||||
|
}
|
||||||
|
if !(flag.Expression == "" || flag.Expression == "true" || flag.Expression == "false") {
|
||||||
|
t.Errorf("the `Expression` property for %s is incorrect. valid values are: `true`, `false` or empty string for default", flag.Name)
|
||||||
|
}
|
||||||
|
// Check camel case names
|
||||||
|
if flag.Name != strcase.ToLowerCamel(flag.Name) && !legacyNames[flag.Name] {
|
||||||
|
invalidNames = append(invalidNames, flag.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the names are valid
|
||||||
|
require.Empty(t, invalidNames, "%s feature names should be camel cased", invalidNames)
|
||||||
|
// acronyms can be configured as needed via `ConfigureAcronym` function from `./strcase/camel.go`
|
||||||
|
}
|
||||||
|
|
||||||
func verifyAndGenerateFile(t *testing.T, fpath string, gen string) {
|
func verifyAndGenerateFile(t *testing.T, fpath string, gen string) {
|
||||||
// nolint:gosec
|
// nolint:gosec
|
||||||
// We can ignore the gosec G304 warning since this is a test and the function is only called explicitly above
|
// We can ignore the gosec G304 warning since this is a test and the function is only called explicitly above
|
||||||
|
Loading…
Reference in New Issue
Block a user