From 6720690615f846ea3762d9d8192220402f0bfc25 Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Mon, 13 Mar 2023 08:07:12 -0700 Subject: [PATCH] FeatureToggles: generate a csv file for easy auditing (#64647) Co-authored-by: Artur Wierzbicki --- pkg/services/featuremgmt/toggles_gen.csv | 66 ++++++++++++++++++++ pkg/services/featuremgmt/toggles_gen.go | 4 +- pkg/services/featuremgmt/toggles_gen_test.go | 58 ++++++++++++----- 3 files changed, 112 insertions(+), 16 deletions(-) create mode 100644 pkg/services/featuremgmt/toggles_gen.csv diff --git a/pkg/services/featuremgmt/toggles_gen.csv b/pkg/services/featuremgmt/toggles_gen.csv new file mode 100644 index 00000000000..42011dd0441 --- /dev/null +++ b/pkg/services/featuremgmt/toggles_gen.csv @@ -0,0 +1,66 @@ +Name,State,Owner,requiresDevMode,RequiresLicense,RequiresRestart,FrontendOnly +alertingBigTransactions,alpha,@grafana/alerting-squad,false,false,false,false +trimDefaults,beta,@grafana/grafana-as-code,false,false,false,false +disableEnvelopeEncryption,stable,@grafana/grafana-as-code,false,false,false,false +database_metrics,stable,@grafana/hosted-grafana-team,false,false,false,false +dashboardPreviews,alpha,@grafana/grafana-app-platform-squad,false,false,false,false +live-pipeline,alpha,@grafana/grafana-app-platform-squad,false,false,false,false +live-service-web-worker,alpha,@grafana/grafana-app-platform-squad,false,false,false,true +queryOverLive,alpha,@grafana/grafana-app-platform-squad,false,false,false,true +panelTitleSearch,beta,@grafana/grafana-app-platform-squad,false,false,false,false +prometheusAzureOverrideAudience,beta,@grafana/observability-metrics,false,false,false,false +publicDashboards,alpha,@grafana/dashboards-squad,false,false,false,false +publicDashboardsEmailSharing,alpha,@grafana/dashboards-squad,false,true,false,false +lokiLive,alpha,@grafana/observability-logs,false,false,false,false +lokiDataframeApi,alpha,@grafana/observability-logs,false,false,false,false +featureHighlights,stable,@grafana/grafana-as-code,false,false,false,false +migrationLocking,beta,@grafana/backend-platform,false,false,false,false +storage,alpha,@grafana/grafana-app-platform-squad,false,false,false,false +k8s,alpha,@grafana/grafana-app-platform-squad,true,false,false,false +dashboardsFromStorage,alpha,@grafana/grafana-app-platform-squad,true,false,false,false +exploreMixedDatasource,alpha,@grafana/explore-squad,false,false,false,true +tracing,alpha,@grafana/user-essentials,false,false,false,true +newTraceView,alpha,@grafana/observability-traces-and-profiling,false,false,false,true +correlations,alpha,@grafana/explore-squad,false,false,false,false +cloudWatchDynamicLabels,stable,@grafana/aws-plugins,false,false,false,false +datasourceQueryMultiStatus,alpha,@grafana/plugins-platform-backend,false,false,false,false +traceToMetrics,alpha,@grafana/observability-traces-and-profiling,false,false,false,true +newDBLibrary,beta,@grafana/backend-platform,false,false,false,false +validateDashboardsOnSave,beta,@grafana/grafana-as-code,false,false,true,false +autoMigrateGraphPanels,beta,@grafana/dataviz-squad,false,false,false,true +prometheusWideSeries,alpha,@grafana/observability-metrics,false,false,false,false +canvasPanelNesting,alpha,@grafana/dataviz-squad,false,false,false,true +scenes,alpha,@grafana/dashboards-squad,false,false,false,true +disableSecretsCompatibility,alpha,@grafana/hosted-grafana-team,false,false,true,false +logRequestsInstrumentedAsUnknown,alpha,@grafana/hosted-grafana-team,false,false,false,false +dataConnectionsConsole,alpha,@grafana/plugins-platform-backend,false,false,false,false +internationalization,stable,@grafana/user-essentials,false,false,false,false +topnav,beta,@grafana/user-essentials,false,false,false,false +grpcServer,alpha,@grafana/grafana-app-platform-squad,true,false,false,false +entityStore,alpha,@grafana/grafana-app-platform-squad,true,false,false,false +cloudWatchCrossAccountQuerying,stable,@grafana/aws-plugins,false,false,false,false +redshiftAsyncQueryDataSupport,alpha,@grafana/aws-plugins,false,false,false,true +athenaAsyncQueryDataSupport,alpha,@grafana/aws-plugins,false,false,false,true +newPanelChromeUI,alpha,@grafana/dashboards-squad,false,false,false,true +queryLibrary,alpha,@grafana/grafana-app-platform-squad,true,false,false,false +showDashboardValidationWarnings,alpha,@grafana/dashboards-squad,false,false,false,false +mysqlAnsiQuotes,alpha,@grafana/backend-platform,false,false,false,false +accessControlOnCall,beta,@grafana/grafana-authnz-team,false,false,false,false +nestedFolders,alpha,@grafana/backend-platform,true,false,false,false +accessTokenExpirationCheck,stable,@grafana/grafana-authnz-team,false,false,false,false +elasticsearchBackendMigration,alpha,@grafana/observability-logs,false,false,false,false +datasourceOnboarding,alpha,@grafana/dashboards-squad,false,false,false,false +secureSocksDatasourceProxy,alpha,@grafana/hosted-grafana-team,false,false,false,false +authnService,alpha,@grafana/grafana-authnz-team,false,false,false,false +disablePrometheusExemplarSampling,stable,@grafana/observability-metrics,false,false,false,false +alertingBacktesting,alpha,@grafana/alerting-squad,false,false,false,false +editPanelCSVDragAndDrop,alpha,@grafana/grafana-bi-squad,false,false,false,true +alertingNoNormalState,beta,@grafana/alerting-squad,false,false,false,false +logsSampleInExplore,stable,@grafana/observability-logs,false,false,false,true +logsContextDatasourceUi,alpha,@grafana/observability-logs,false,false,false,true +lokiQuerySplitting,alpha,@grafana/observability-logs,false,false,false,true +individualCookiePreferences,alpha,@grafana/backend-platform,false,false,false,false +drawerDataSourcePicker,alpha,@grafana/grafana-bi-squad,false,false,false,true +traceqlSearch,alpha,@grafana/observability-traces-and-profiling,false,false,false,true +prometheusMetricEncyclopedia,alpha,@grafana/observability-metrics,false,false,false,true +timeSeriesTable,alpha,@grafana/app-o11y,false,false,false,true diff --git a/pkg/services/featuremgmt/toggles_gen.go b/pkg/services/featuremgmt/toggles_gen.go index 8e4bb4265e9..5b57828980d 100644 --- a/pkg/services/featuremgmt/toggles_gen.go +++ b/pkg/services/featuremgmt/toggles_gen.go @@ -75,9 +75,9 @@ const ( // Configurable storage for dashboards, datasources, and resources FlagStorage = "storage" - // FlagK8s + // FlagK8S // Explore native k8s integrations - FlagK8s = "k8s" + FlagK8S = "k8s" // FlagDashboardsFromStorage // Load dashboards from the generic storage interface diff --git a/pkg/services/featuremgmt/toggles_gen_test.go b/pkg/services/featuremgmt/toggles_gen_test.go index e55096e9476..ae61f5e7c9c 100644 --- a/pkg/services/featuremgmt/toggles_gen_test.go +++ b/pkg/services/featuremgmt/toggles_gen_test.go @@ -2,13 +2,15 @@ package featuremgmt import ( "bytes" + "encoding/csv" "fmt" "html/template" + "log" "os" "path/filepath" + "strconv" "strings" "testing" - "unicode" "github.com/google/go-cmp/cmp" "github.com/olekukonko/tablewriter" @@ -67,6 +69,12 @@ func TestFeatureToggleFiles(t *testing.T) { "../../../docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md", generateDocsMD(), ) + + // CSV Analytics + verifyAndGenerateFile(t, + "toggles_gen.csv", + generateCSV(), + ) }) t.Run("check feature naming convention", func(t *testing.T) { @@ -143,18 +151,6 @@ func getTypeScriptKey(key string) string { return key } -func isLetterOrNumber(c rune) bool { - return !unicode.IsLetter(c) && !unicode.IsNumber(c) -} - -func asCamelCase(key string) string { - parts := strings.FieldsFunc(key, isLetterOrNumber) - for idx, part := range parts { - parts[idx] = strings.Title(part) - } - return strings.Join(parts, "") -} - func generateRegistry(t *testing.T) string { tmpl, err := template.New("fn").Parse(` {{"\t"}}// Flag{{.CamelCase}}{{.Ext}} @@ -186,7 +182,7 @@ package featuremgmt const (`) for _, flag := range standardFeatureFlags { - data.CamelCase = asCamelCase(flag.Name) + data.CamelCase = strcase.ToCamel(flag.Name) data.Flag = flag data.Ext = "" @@ -201,6 +197,40 @@ const (`) return buff.String() } +func generateCSV() string { + var buf bytes.Buffer + + w := csv.NewWriter(&buf) + if err := w.Write([]string{ + "Name", + "State", //flag.State.String(), + "Owner", // string(flag.Owner), + "requiresDevMode", //strconv.FormatBool(flag.RequiresDevMode), + "RequiresLicense", //strconv.FormatBool(flag.RequiresLicense), + "RequiresRestart", //strconv.FormatBool(flag.RequiresRestart), + "FrontendOnly", //strconv.FormatBool(flag.FrontendOnly), + }); err != nil { + log.Fatalln("error writing record to csv:", err) + } + + for _, flag := range standardFeatureFlags { + if err := w.Write([]string{ + flag.Name, + flag.State.String(), + string(flag.Owner), + strconv.FormatBool(flag.RequiresDevMode), + strconv.FormatBool(flag.RequiresLicense), + strconv.FormatBool(flag.RequiresRestart), + strconv.FormatBool(flag.FrontendOnly), + }); err != nil { + log.Fatalln("error writing record to csv:", err) + } + } + + w.Flush() + return buf.String() +} + func generateDocsMD() string { hasDeprecatedFlags := false