FeatureFlags: manage creation/modification times automatically (#82131)

This commit is contained in:
Ryan McKinley
2024-02-09 15:34:12 -08:00
committed by GitHub
parent 14869cc400
commit ce910a7eb2
7 changed files with 2336 additions and 394 deletions

View File

@ -3,7 +3,7 @@ package featuretoggle
import (
"context"
"fmt"
"time"
"sync"
"k8s.io/apimachinery/pkg/apis/meta/internalversion"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -27,18 +27,16 @@ var (
type featuresStorage struct {
resource *common.ResourceInfo
tableConverter rest.TableConvertor
features []featuremgmt.FeatureFlag
startup int64
features *v0alpha1.FeatureList
featuresOnce sync.Once
}
// NOTE! this does not depend on config or any system state!
// In the future, the existence of features (and their properties) can be defined dynamically
func NewFeaturesStorage(features []featuremgmt.FeatureFlag) *featuresStorage {
func NewFeaturesStorage() *featuresStorage {
resourceInfo := v0alpha1.FeatureResourceInfo
return &featuresStorage{
startup: time.Now().UnixMilli(),
resource: &resourceInfo,
features: features,
tableConverter: utils.NewTableConverter(
resourceInfo.GroupResource(),
[]metav1.TableColumnDefinition{
@ -82,44 +80,35 @@ func (s *featuresStorage) ConvertToTable(ctx context.Context, object runtime.Obj
return s.tableConverter.ConvertToTable(ctx, object, tableOptions)
}
func (s *featuresStorage) init() {
s.featuresOnce.Do(func() {
rv := "1"
features, _ := featuremgmt.GetEmbeddedFeatureList()
for _, feature := range features.Items {
if feature.ResourceVersion > rv {
rv = feature.ResourceVersion
}
}
features.ResourceVersion = rv
s.features = &features
})
}
func (s *featuresStorage) List(ctx context.Context, options *internalversion.ListOptions) (runtime.Object, error) {
flags := &v0alpha1.FeatureList{
ListMeta: metav1.ListMeta{
ResourceVersion: fmt.Sprintf("%d", s.startup),
},
s.init()
if s.features == nil {
return nil, fmt.Errorf("error loading embedded features")
}
for _, flag := range s.features {
flags.Items = append(flags.Items, toK8sForm(flag))
}
return flags, nil
return s.features, nil
}
func (s *featuresStorage) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
for _, flag := range s.features {
if name == flag.Name {
obj := toK8sForm(flag)
return &obj, nil
s.init()
for idx, flag := range s.features.Items {
if flag.Name == name {
return &s.features.Items[idx], nil
}
}
return nil, fmt.Errorf("not found")
}
func toK8sForm(flag featuremgmt.FeatureFlag) v0alpha1.Feature {
return v0alpha1.Feature{
ObjectMeta: metav1.ObjectMeta{
Name: flag.Name,
CreationTimestamp: metav1.NewTime(flag.Created),
},
Spec: v0alpha1.FeatureSpec{
Description: flag.Description,
Stage: flag.Stage.String(),
Owner: string(flag.Owner),
AllowSelfServe: flag.AllowSelfServe,
HideFromAdminPage: flag.HideFromAdminPage,
HideFromDocs: flag.HideFromDocs,
FrontendOnly: flag.FrontendOnly,
RequiresDevMode: flag.RequiresDevMode,
RequiresRestart: flag.RequiresRestart,
},
}
}

View File

@ -86,7 +86,7 @@ func (b *FeatureFlagAPIBuilder) GetAPIGroupInfo(
) (*genericapiserver.APIGroupInfo, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(v0alpha1.GROUP, scheme, metav1.ParameterCodec, codecs)
featureStore := NewFeaturesStorage(b.features.GetFlags())
featureStore := NewFeaturesStorage()
toggleStore := NewTogglesStorage(b.features)
storage := map[string]rest.Storage{}

View File

@ -4,7 +4,6 @@ import (
"bytes"
"context"
"encoding/json"
"time"
)
type FeatureToggles interface {
@ -115,8 +114,7 @@ type FeatureFlag struct {
Name string `json:"name" yaml:"name"` // Unique name
Description string `json:"description"`
Stage FeatureFlagStage `json:"stage,omitempty"`
Created time.Time `json:"created,omitempty"` // when the flag was introduced
Owner codeowner `json:"-"` // Owner person or team that owns this feature flag
Owner codeowner `json:"-"` // Owner person or team that owns this feature flag
// Recommended properties - control behavior of the feature toggle management page in the UI
AllowSelfServe bool `json:"allowSelfServe,omitempty"` // allow users with the right privileges to toggle this from the UI (GeneralAvailability, PublicPreview, and Deprecated toggles only)

File diff suppressed because it is too large Load Diff

View File

@ -1,158 +1,158 @@
Name,Stage,Owner,Created,requiresDevMode,RequiresRestart,FrontendOnly
disableEnvelopeEncryption,GA,@grafana/grafana-as-code,2022-05-24,false,false,false
live-service-web-worker,experimental,@grafana/grafana-app-platform-squad,2021-11-09,false,false,true
queryOverLive,experimental,@grafana/grafana-app-platform-squad,2022-01-05,false,false,true
panelTitleSearch,preview,@grafana/grafana-app-platform-squad,2022-02-15,false,false,false
publicDashboards,GA,@grafana/sharing-squad,2022-04-07,false,false,false
publicDashboardsEmailSharing,preview,@grafana/sharing-squad,2022-12-21,false,false,false
lokiExperimentalStreaming,experimental,@grafana/observability-logs,2023-06-19,false,false,false
featureHighlights,GA,@grafana/grafana-as-code,2022-02-03,false,false,false
migrationLocking,preview,@grafana/backend-platform,2022-02-15,false,false,false
storage,experimental,@grafana/grafana-app-platform-squad,2022-03-17,false,false,false
correlations,GA,@grafana/explore-squad,2022-09-16,false,false,false
exploreContentOutline,GA,@grafana/explore-squad,2023-11-03,false,false,true
datasourceQueryMultiStatus,experimental,@grafana/plugins-platform-backend,2022-05-03,false,false,false
traceToMetrics,experimental,@grafana/observability-traces-and-profiling,2022-03-07,false,false,true
autoMigrateOldPanels,preview,@grafana/dataviz-squad,2022-06-11,false,false,true
autoMigrateGraphPanel,preview,@grafana/dataviz-squad,2023-12-11,false,false,true
disableAngular,preview,@grafana/dataviz-squad,2023-03-23,false,false,true
canvasPanelNesting,experimental,@grafana/dataviz-squad,2022-05-31,false,false,true
newVizTooltips,preview,@grafana/dataviz-squad,2023-11-03,false,false,true
scenes,experimental,@grafana/dashboards-squad,2022-07-07,false,false,true
disableSecretsCompatibility,experimental,@grafana/hosted-grafana-team,2022-07-13,false,true,false
logRequestsInstrumentedAsUnknown,experimental,@grafana/hosted-grafana-team,2022-06-10,false,false,false
dataConnectionsConsole,GA,@grafana/plugins-platform-backend,2022-06-01,false,false,false
topnav,deprecated,@grafana/grafana-frontend-platform,2022-06-20,false,false,false
returnToPrevious,experimental,@grafana/grafana-frontend-platform,2024-01-09,false,false,true
grpcServer,preview,@grafana/grafana-app-platform-squad,2022-09-27,false,false,false
unifiedStorage,experimental,@grafana/grafana-app-platform-squad,2022-12-01,true,true,false
cloudWatchCrossAccountQuerying,GA,@grafana/aws-datasources,2022-11-28,false,false,false
redshiftAsyncQueryDataSupport,GA,@grafana/aws-datasources,2022-08-27,false,false,false
athenaAsyncQueryDataSupport,GA,@grafana/aws-datasources,2022-08-27,false,false,true
showDashboardValidationWarnings,experimental,@grafana/dashboards-squad,2022-10-14,false,false,false
mysqlAnsiQuotes,experimental,@grafana/backend-platform,2022-10-12,false,false,false
accessControlOnCall,preview,@grafana/identity-access-team,2022-10-19,false,false,false
nestedFolders,preview,@grafana/backend-platform,2022-10-22,false,false,false
nestedFolderPicker,GA,@grafana/grafana-frontend-platform,2023-07-24,false,false,true
alertingBacktesting,experimental,@grafana/alerting-squad,2022-10-20,false,false,false
editPanelCSVDragAndDrop,experimental,@grafana/grafana-bi-squad,2022-12-20,false,false,true
alertingNoNormalState,preview,@grafana/alerting-squad,2023-01-14,false,false,false
logsContextDatasourceUi,GA,@grafana/observability-logs,2023-01-27,false,false,true
lokiQuerySplitting,GA,@grafana/observability-logs,2023-02-09,false,false,true
lokiQuerySplittingConfig,experimental,@grafana/observability-logs,2023-03-20,false,false,true
individualCookiePreferences,experimental,@grafana/backend-platform,2023-02-23,false,false,false
prometheusMetricEncyclopedia,GA,@grafana/observability-metrics,2023-03-07,false,false,true
influxdbBackendMigration,GA,@grafana/observability-metrics,2023-03-15,false,false,true
influxqlStreamingParser,experimental,@grafana/observability-metrics,2023-11-29,false,false,false
influxdbRunQueriesInParallel,privatePreview,@grafana/observability-metrics,2024-01-29,false,false,false
clientTokenRotation,GA,@grafana/identity-access-team,2023-03-23,false,false,false
prometheusDataplane,GA,@grafana/observability-metrics,2023-03-29,false,false,false
lokiMetricDataplane,GA,@grafana/observability-logs,2023-04-13,false,false,false
lokiLogsDataplane,experimental,@grafana/observability-logs,2023-07-13,false,false,false
dataplaneFrontendFallback,GA,@grafana/observability-metrics,2023-04-24,false,false,true
disableSSEDataplane,experimental,@grafana/observability-metrics,2023-04-24,false,false,false
alertStateHistoryLokiSecondary,experimental,@grafana/alerting-squad,2023-03-30,false,false,false
alertStateHistoryLokiPrimary,experimental,@grafana/alerting-squad,2023-03-30,false,false,false
alertStateHistoryLokiOnly,experimental,@grafana/alerting-squad,2023-03-30,false,false,false
unifiedRequestLog,experimental,@grafana/backend-platform,2023-03-31,false,false,false
renderAuthJWT,preview,@grafana/grafana-as-code,2023-04-03,false,false,false
externalServiceAuth,experimental,@grafana/identity-access-team,2023-04-11,true,false,false
refactorVariablesTimeRange,preview,@grafana/dashboards-squad,2023-06-06,false,false,false
enableElasticsearchBackendQuerying,GA,@grafana/observability-logs,2023-04-14,false,false,false
faroDatasourceSelector,preview,@grafana/app-o11y,2023-05-04,false,false,true
enableDatagridEditing,preview,@grafana/grafana-bi-squad,2023-04-24,false,false,true
extraThemes,experimental,@grafana/grafana-frontend-platform,2023-05-10,false,false,true
lokiPredefinedOperations,experimental,@grafana/observability-logs,2023-06-02,false,false,true
pluginsFrontendSandbox,experimental,@grafana/plugins-platform-backend,2023-06-05,false,false,true
dashboardEmbed,experimental,@grafana/grafana-as-code,2023-07-06,false,false,true
frontendSandboxMonitorOnly,experimental,@grafana/plugins-platform-backend,2023-07-05,false,false,true
sqlDatasourceDatabaseSelection,preview,@grafana/grafana-bi-squad,2023-06-06,false,false,true
lokiFormatQuery,experimental,@grafana/observability-logs,2023-06-21,false,false,true
cloudWatchLogsMonacoEditor,GA,@grafana/aws-datasources,2023-06-12,false,false,true
exploreScrollableLogsContainer,experimental,@grafana/observability-logs,2023-06-15,false,false,true
recordedQueriesMulti,GA,@grafana/observability-metrics,2023-06-14,false,false,false
pluginsDynamicAngularDetectionPatterns,experimental,@grafana/plugins-platform-backend,2023-06-26,false,false,false
vizAndWidgetSplit,experimental,@grafana/dashboards-squad,2023-06-27,false,false,true
prometheusIncrementalQueryInstrumentation,experimental,@grafana/observability-metrics,2023-07-05,false,false,true
logsExploreTableVisualisation,experimental,@grafana/observability-logs,2023-07-12,false,false,true
awsDatasourcesTempCredentials,experimental,@grafana/aws-datasources,2023-07-06,false,false,false
transformationsRedesign,GA,@grafana/observability-metrics,2023-07-12,false,false,true
mlExpressions,experimental,@grafana/alerting-squad,2023-07-13,false,false,false
traceQLStreaming,experimental,@grafana/observability-traces-and-profiling,2023-07-26,false,false,true
metricsSummary,experimental,@grafana/observability-traces-and-profiling,2023-08-28,false,false,true
grafanaAPIServerWithExperimentalAPIs,experimental,@grafana/grafana-app-platform-squad,2023-10-06,true,true,false
grafanaAPIServerEnsureKubectlAccess,experimental,@grafana/grafana-app-platform-squad,2023-12-06,true,true,false
featureToggleAdminPage,experimental,@grafana/grafana-operator-experience-squad,2023-07-18,false,true,false
awsAsyncQueryCaching,GA,@grafana/aws-datasources,2023-07-21,false,false,false
splitScopes,deprecated,@grafana/identity-access-team,2023-07-21,false,true,false
permissionsFilterRemoveSubquery,experimental,@grafana/backend-platform,2023-08-02,false,false,false
prometheusConfigOverhaulAuth,GA,@grafana/observability-metrics,2023-07-21,false,false,false
configurableSchedulerTick,experimental,@grafana/alerting-squad,2023-07-26,false,true,false
influxdbSqlSupport,GA,@grafana/observability-metrics,2023-08-02,false,true,false
alertingNoDataErrorExecution,GA,@grafana/alerting-squad,2023-08-15,false,true,false
angularDeprecationUI,experimental,@grafana/plugins-platform-backend,2023-08-29,false,false,true
dashgpt,preview,@grafana/dashboards-squad,2023-11-17,false,false,true
reportingRetries,preview,@grafana/sharing-squad,2023-08-31,false,true,false
sseGroupByDatasource,experimental,@grafana/observability-metrics,2023-09-07,false,false,false
libraryPanelRBAC,experimental,@grafana/dashboards-squad,2023-10-11,false,true,false
lokiRunQueriesInParallel,privatePreview,@grafana/observability-logs,2023-09-19,false,false,false
wargamesTesting,experimental,@grafana/hosted-grafana-team,2023-09-13,false,false,false
alertingInsights,GA,@grafana/alerting-squad,2023-09-14,false,false,true
externalCorePlugins,experimental,@grafana/plugins-platform-backend,2023-09-22,false,false,false
pluginsAPIMetrics,experimental,@grafana/plugins-platform-backend,2023-09-21,false,false,true
idForwarding,experimental,@grafana/identity-access-team,2023-09-25,false,false,false
cloudWatchWildCardDimensionValues,GA,@grafana/aws-datasources,2023-09-27,false,false,false
externalServiceAccounts,preview,@grafana/identity-access-team,2023-09-28,false,false,false
panelMonitoring,experimental,@grafana/dataviz-squad,2023-10-08,false,false,true
enableNativeHTTPHistogram,experimental,@grafana/hosted-grafana-team,2023-10-03,false,false,false
formatString,preview,@grafana/grafana-bi-squad,2023-10-13,false,false,true
transformationsVariableSupport,preview,@grafana/grafana-bi-squad,2023-10-04,false,false,true
kubernetesPlaylists,experimental,@grafana/grafana-app-platform-squad,2023-11-08,false,true,false
kubernetesSnapshots,experimental,@grafana/grafana-app-platform-squad,2023-12-04,false,true,false
kubernetesQueryServiceRewrite,experimental,@grafana/grafana-app-platform-squad,2024-01-28,true,true,false
cloudWatchBatchQueries,preview,@grafana/aws-datasources,2023-10-20,false,false,false
recoveryThreshold,GA,@grafana/alerting-squad,2023-10-10,false,true,false
lokiStructuredMetadata,experimental,@grafana/observability-logs,2023-11-16,false,false,false
teamHttpHeaders,experimental,@grafana/identity-access-team,2023-10-17,false,false,false
awsDatasourcesNewFormStyling,preview,@grafana/aws-datasources,2023-10-12,false,false,true
cachingOptimizeSerializationMemoryUsage,experimental,@grafana/grafana-operator-experience-squad,2023-10-12,false,false,false
panelTitleSearchInV1,experimental,@grafana/backend-platform,2023-10-13,true,false,false
pluginsInstrumentationStatusSource,experimental,@grafana/plugins-platform-backend,2023-10-17,false,false,false
managedPluginsInstall,preview,@grafana/plugins-platform-backend,2023-10-18,false,false,false
prometheusPromQAIL,experimental,@grafana/observability-metrics,2023-10-19,false,false,true
addFieldFromCalculationStatFunctions,preview,@grafana/grafana-bi-squad,2023-11-03,false,false,true
alertmanagerRemoteSecondary,experimental,@grafana/alerting-squad,2023-10-30,false,false,false
alertmanagerRemotePrimary,experimental,@grafana/alerting-squad,2023-10-30,false,false,false
alertmanagerRemoteOnly,experimental,@grafana/alerting-squad,2023-10-30,false,false,false
annotationPermissionUpdate,experimental,@grafana/identity-access-team,2023-10-31,false,false,false
extractFieldsNameDeduplication,experimental,@grafana/grafana-bi-squad,2023-11-02,false,false,true
dashboardSceneForViewers,experimental,@grafana/dashboards-squad,2023-11-02,false,false,true
dashboardScene,experimental,@grafana/dashboards-squad,2023-11-13,false,false,true
panelFilterVariable,experimental,@grafana/dashboards-squad,2023-11-03,false,false,true
pdfTables,preview,@grafana/sharing-squad,2023-11-06,false,false,false
ssoSettingsApi,experimental,@grafana/identity-access-team,2023-11-08,false,false,false
canvasPanelPanZoom,preview,@grafana/dataviz-squad,2023-12-27,false,false,true
logsInfiniteScrolling,experimental,@grafana/observability-logs,2023-11-09,false,false,true
flameGraphItemCollapsing,experimental,@grafana/observability-traces-and-profiling,2023-11-09,false,false,true
alertingDetailsViewV2,experimental,@grafana/alerting-squad,2023-11-09,false,false,true
datatrails,experimental,@grafana/dashboards-squad,2023-11-15,false,false,true
alertingSimplifiedRouting,experimental,@grafana/alerting-squad,2023-11-10,false,false,false
logRowsPopoverMenu,GA,@grafana/observability-logs,2023-11-16,false,false,true
pluginsSkipHostEnvVars,experimental,@grafana/plugins-platform-backend,2023-11-15,false,false,false
tableSharedCrosshair,experimental,@grafana/grafana-bi-squad,2023-12-12,false,false,true
regressionTransformation,preview,@grafana/grafana-bi-squad,2023-11-24,false,false,true
displayAnonymousStats,GA,@grafana/identity-access-team,2023-11-29,false,false,true
lokiQueryHints,GA,@grafana/observability-logs,2023-12-18,false,false,true
kubernetesFeatureToggles,experimental,@grafana/grafana-operator-experience-squad,2023-12-22,false,false,true
alertingPreviewUpgrade,GA,@grafana/alerting-squad,2024-01-03,false,true,false
enablePluginsTracingByDefault,experimental,@grafana/plugins-platform-backend,2024-01-09,false,true,false
cloudRBACRoles,experimental,@grafana/identity-access-team,2024-01-10,false,true,false
alertingQueryOptimization,GA,@grafana/alerting-squad,2024-01-10,false,false,false
newFolderPicker,experimental,@grafana/grafana-frontend-platform,2024-01-12,false,false,true
jitterAlertRulesWithinGroups,preview,@grafana/alerting-squad,2024-01-17,false,true,false
onPremToCloudMigrations,experimental,@grafana/grafana-operator-experience-squad,2024-01-22,false,false,false
alertingSaveStatePeriodic,privatePreview,@grafana/alerting-squad,2024-01-22,false,false,false
promQLScope,experimental,@grafana/observability-metrics,2024-01-29,false,false,false
nodeGraphDotLayout,experimental,@grafana/observability-traces-and-profiling,2024-01-02,false,false,true
groupToNestedTableTransformation,preview,@grafana/dataviz-squad,2024-02-05,false,false,true
newPDFRendering,experimental,@grafana/sharing-squad,2024-02-08,false,false,false
Name,Stage,Owner,requiresDevMode,RequiresRestart,FrontendOnly
disableEnvelopeEncryption,GA,@grafana/grafana-as-code,false,false,false
live-service-web-worker,experimental,@grafana/grafana-app-platform-squad,false,false,true
queryOverLive,experimental,@grafana/grafana-app-platform-squad,false,false,true
panelTitleSearch,preview,@grafana/grafana-app-platform-squad,false,false,false
publicDashboards,GA,@grafana/sharing-squad,false,false,false
publicDashboardsEmailSharing,preview,@grafana/sharing-squad,false,false,false
lokiExperimentalStreaming,experimental,@grafana/observability-logs,false,false,false
featureHighlights,GA,@grafana/grafana-as-code,false,false,false
migrationLocking,preview,@grafana/backend-platform,false,false,false
storage,experimental,@grafana/grafana-app-platform-squad,false,false,false
correlations,GA,@grafana/explore-squad,false,false,false
exploreContentOutline,GA,@grafana/explore-squad,false,false,true
datasourceQueryMultiStatus,experimental,@grafana/plugins-platform-backend,false,false,false
traceToMetrics,experimental,@grafana/observability-traces-and-profiling,false,false,true
autoMigrateOldPanels,preview,@grafana/dataviz-squad,false,false,true
autoMigrateGraphPanel,preview,@grafana/dataviz-squad,false,false,true
disableAngular,preview,@grafana/dataviz-squad,false,false,true
canvasPanelNesting,experimental,@grafana/dataviz-squad,false,false,true
newVizTooltips,preview,@grafana/dataviz-squad,false,false,true
scenes,experimental,@grafana/dashboards-squad,false,false,true
disableSecretsCompatibility,experimental,@grafana/hosted-grafana-team,false,true,false
logRequestsInstrumentedAsUnknown,experimental,@grafana/hosted-grafana-team,false,false,false
dataConnectionsConsole,GA,@grafana/plugins-platform-backend,false,false,false
topnav,deprecated,@grafana/grafana-frontend-platform,false,false,false
returnToPrevious,experimental,@grafana/grafana-frontend-platform,false,false,true
grpcServer,preview,@grafana/grafana-app-platform-squad,false,false,false
unifiedStorage,experimental,@grafana/grafana-app-platform-squad,true,true,false
cloudWatchCrossAccountQuerying,GA,@grafana/aws-datasources,false,false,false
redshiftAsyncQueryDataSupport,GA,@grafana/aws-datasources,false,false,false
athenaAsyncQueryDataSupport,GA,@grafana/aws-datasources,false,false,true
showDashboardValidationWarnings,experimental,@grafana/dashboards-squad,false,false,false
mysqlAnsiQuotes,experimental,@grafana/backend-platform,false,false,false
accessControlOnCall,preview,@grafana/identity-access-team,false,false,false
nestedFolders,preview,@grafana/backend-platform,false,false,false
nestedFolderPicker,GA,@grafana/grafana-frontend-platform,false,false,true
alertingBacktesting,experimental,@grafana/alerting-squad,false,false,false
editPanelCSVDragAndDrop,experimental,@grafana/grafana-bi-squad,false,false,true
alertingNoNormalState,preview,@grafana/alerting-squad,false,false,false
logsContextDatasourceUi,GA,@grafana/observability-logs,false,false,true
lokiQuerySplitting,GA,@grafana/observability-logs,false,false,true
lokiQuerySplittingConfig,experimental,@grafana/observability-logs,false,false,true
individualCookiePreferences,experimental,@grafana/backend-platform,false,false,false
prometheusMetricEncyclopedia,GA,@grafana/observability-metrics,false,false,true
influxdbBackendMigration,GA,@grafana/observability-metrics,false,false,true
influxqlStreamingParser,experimental,@grafana/observability-metrics,false,false,false
influxdbRunQueriesInParallel,privatePreview,@grafana/observability-metrics,false,false,false
clientTokenRotation,GA,@grafana/identity-access-team,false,false,false
prometheusDataplane,GA,@grafana/observability-metrics,false,false,false
lokiMetricDataplane,GA,@grafana/observability-logs,false,false,false
lokiLogsDataplane,experimental,@grafana/observability-logs,false,false,false
dataplaneFrontendFallback,GA,@grafana/observability-metrics,false,false,true
disableSSEDataplane,experimental,@grafana/observability-metrics,false,false,false
alertStateHistoryLokiSecondary,experimental,@grafana/alerting-squad,false,false,false
alertStateHistoryLokiPrimary,experimental,@grafana/alerting-squad,false,false,false
alertStateHistoryLokiOnly,experimental,@grafana/alerting-squad,false,false,false
unifiedRequestLog,experimental,@grafana/backend-platform,false,false,false
renderAuthJWT,preview,@grafana/grafana-as-code,false,false,false
externalServiceAuth,experimental,@grafana/identity-access-team,true,false,false
refactorVariablesTimeRange,preview,@grafana/dashboards-squad,false,false,false
enableElasticsearchBackendQuerying,GA,@grafana/observability-logs,false,false,false
faroDatasourceSelector,preview,@grafana/app-o11y,false,false,true
enableDatagridEditing,preview,@grafana/grafana-bi-squad,false,false,true
extraThemes,experimental,@grafana/grafana-frontend-platform,false,false,true
lokiPredefinedOperations,experimental,@grafana/observability-logs,false,false,true
pluginsFrontendSandbox,experimental,@grafana/plugins-platform-backend,false,false,true
dashboardEmbed,experimental,@grafana/grafana-as-code,false,false,true
frontendSandboxMonitorOnly,experimental,@grafana/plugins-platform-backend,false,false,true
sqlDatasourceDatabaseSelection,preview,@grafana/grafana-bi-squad,false,false,true
lokiFormatQuery,experimental,@grafana/observability-logs,false,false,true
cloudWatchLogsMonacoEditor,GA,@grafana/aws-datasources,false,false,true
exploreScrollableLogsContainer,experimental,@grafana/observability-logs,false,false,true
recordedQueriesMulti,GA,@grafana/observability-metrics,false,false,false
pluginsDynamicAngularDetectionPatterns,experimental,@grafana/plugins-platform-backend,false,false,false
vizAndWidgetSplit,experimental,@grafana/dashboards-squad,false,false,true
prometheusIncrementalQueryInstrumentation,experimental,@grafana/observability-metrics,false,false,true
logsExploreTableVisualisation,experimental,@grafana/observability-logs,false,false,true
awsDatasourcesTempCredentials,experimental,@grafana/aws-datasources,false,false,false
transformationsRedesign,GA,@grafana/observability-metrics,false,false,true
mlExpressions,experimental,@grafana/alerting-squad,false,false,false
traceQLStreaming,experimental,@grafana/observability-traces-and-profiling,false,false,true
metricsSummary,experimental,@grafana/observability-traces-and-profiling,false,false,true
grafanaAPIServerWithExperimentalAPIs,experimental,@grafana/grafana-app-platform-squad,true,true,false
grafanaAPIServerEnsureKubectlAccess,experimental,@grafana/grafana-app-platform-squad,true,true,false
featureToggleAdminPage,experimental,@grafana/grafana-operator-experience-squad,false,true,false
awsAsyncQueryCaching,GA,@grafana/aws-datasources,false,false,false
splitScopes,deprecated,@grafana/identity-access-team,false,true,false
permissionsFilterRemoveSubquery,experimental,@grafana/backend-platform,false,false,false
prometheusConfigOverhaulAuth,GA,@grafana/observability-metrics,false,false,false
configurableSchedulerTick,experimental,@grafana/alerting-squad,false,true,false
influxdbSqlSupport,GA,@grafana/observability-metrics,false,true,false
alertingNoDataErrorExecution,GA,@grafana/alerting-squad,false,true,false
angularDeprecationUI,experimental,@grafana/plugins-platform-backend,false,false,true
dashgpt,preview,@grafana/dashboards-squad,false,false,true
reportingRetries,preview,@grafana/sharing-squad,false,true,false
sseGroupByDatasource,experimental,@grafana/observability-metrics,false,false,false
libraryPanelRBAC,experimental,@grafana/dashboards-squad,false,true,false
lokiRunQueriesInParallel,privatePreview,@grafana/observability-logs,false,false,false
wargamesTesting,experimental,@grafana/hosted-grafana-team,false,false,false
alertingInsights,GA,@grafana/alerting-squad,false,false,true
externalCorePlugins,experimental,@grafana/plugins-platform-backend,false,false,false
pluginsAPIMetrics,experimental,@grafana/plugins-platform-backend,false,false,true
idForwarding,experimental,@grafana/identity-access-team,false,false,false
cloudWatchWildCardDimensionValues,GA,@grafana/aws-datasources,false,false,false
externalServiceAccounts,preview,@grafana/identity-access-team,false,false,false
panelMonitoring,experimental,@grafana/dataviz-squad,false,false,true
enableNativeHTTPHistogram,experimental,@grafana/hosted-grafana-team,false,false,false
formatString,preview,@grafana/grafana-bi-squad,false,false,true
transformationsVariableSupport,preview,@grafana/grafana-bi-squad,false,false,true
kubernetesPlaylists,experimental,@grafana/grafana-app-platform-squad,false,true,false
kubernetesSnapshots,experimental,@grafana/grafana-app-platform-squad,false,true,false
kubernetesQueryServiceRewrite,experimental,@grafana/grafana-app-platform-squad,true,true,false
cloudWatchBatchQueries,preview,@grafana/aws-datasources,false,false,false
recoveryThreshold,GA,@grafana/alerting-squad,false,true,false
lokiStructuredMetadata,experimental,@grafana/observability-logs,false,false,false
teamHttpHeaders,experimental,@grafana/identity-access-team,false,false,false
awsDatasourcesNewFormStyling,preview,@grafana/aws-datasources,false,false,true
cachingOptimizeSerializationMemoryUsage,experimental,@grafana/grafana-operator-experience-squad,false,false,false
panelTitleSearchInV1,experimental,@grafana/backend-platform,true,false,false
pluginsInstrumentationStatusSource,experimental,@grafana/plugins-platform-backend,false,false,false
managedPluginsInstall,preview,@grafana/plugins-platform-backend,false,false,false
prometheusPromQAIL,experimental,@grafana/observability-metrics,false,false,true
addFieldFromCalculationStatFunctions,preview,@grafana/grafana-bi-squad,false,false,true
alertmanagerRemoteSecondary,experimental,@grafana/alerting-squad,false,false,false
alertmanagerRemotePrimary,experimental,@grafana/alerting-squad,false,false,false
alertmanagerRemoteOnly,experimental,@grafana/alerting-squad,false,false,false
annotationPermissionUpdate,experimental,@grafana/identity-access-team,false,false,false
extractFieldsNameDeduplication,experimental,@grafana/grafana-bi-squad,false,false,true
dashboardSceneForViewers,experimental,@grafana/dashboards-squad,false,false,true
dashboardScene,experimental,@grafana/dashboards-squad,false,false,true
panelFilterVariable,experimental,@grafana/dashboards-squad,false,false,true
pdfTables,preview,@grafana/sharing-squad,false,false,false
ssoSettingsApi,experimental,@grafana/identity-access-team,false,false,false
canvasPanelPanZoom,preview,@grafana/dataviz-squad,false,false,true
logsInfiniteScrolling,experimental,@grafana/observability-logs,false,false,true
flameGraphItemCollapsing,experimental,@grafana/observability-traces-and-profiling,false,false,true
alertingDetailsViewV2,experimental,@grafana/alerting-squad,false,false,true
datatrails,experimental,@grafana/dashboards-squad,false,false,true
alertingSimplifiedRouting,experimental,@grafana/alerting-squad,false,false,false
logRowsPopoverMenu,GA,@grafana/observability-logs,false,false,true
pluginsSkipHostEnvVars,experimental,@grafana/plugins-platform-backend,false,false,false
tableSharedCrosshair,experimental,@grafana/grafana-bi-squad,false,false,true
regressionTransformation,preview,@grafana/grafana-bi-squad,false,false,true
displayAnonymousStats,GA,@grafana/identity-access-team,false,false,true
lokiQueryHints,GA,@grafana/observability-logs,false,false,true
kubernetesFeatureToggles,experimental,@grafana/grafana-operator-experience-squad,false,false,true
alertingPreviewUpgrade,GA,@grafana/alerting-squad,false,true,false
enablePluginsTracingByDefault,experimental,@grafana/plugins-platform-backend,false,true,false
cloudRBACRoles,experimental,@grafana/identity-access-team,false,true,false
alertingQueryOptimization,GA,@grafana/alerting-squad,false,false,false
newFolderPicker,experimental,@grafana/grafana-frontend-platform,false,false,true
jitterAlertRulesWithinGroups,preview,@grafana/alerting-squad,false,true,false
onPremToCloudMigrations,experimental,@grafana/grafana-operator-experience-squad,false,false,false
alertingSaveStatePeriodic,privatePreview,@grafana/alerting-squad,false,false,false
promQLScope,experimental,@grafana/observability-metrics,false,false,false
nodeGraphDotLayout,experimental,@grafana/observability-traces-and-profiling,false,false,true
groupToNestedTableTransformation,preview,@grafana/dataviz-squad,false,false,true
newPDFRendering,experimental,@grafana/sharing-squad,false,false,false

1 Name Stage Owner Created requiresDevMode RequiresRestart FrontendOnly
2 disableEnvelopeEncryption GA @grafana/grafana-as-code 2022-05-24 false false false
3 live-service-web-worker experimental @grafana/grafana-app-platform-squad 2021-11-09 false false true
4 queryOverLive experimental @grafana/grafana-app-platform-squad 2022-01-05 false false true
5 panelTitleSearch preview @grafana/grafana-app-platform-squad 2022-02-15 false false false
6 publicDashboards GA @grafana/sharing-squad 2022-04-07 false false false
7 publicDashboardsEmailSharing preview @grafana/sharing-squad 2022-12-21 false false false
8 lokiExperimentalStreaming experimental @grafana/observability-logs 2023-06-19 false false false
9 featureHighlights GA @grafana/grafana-as-code 2022-02-03 false false false
10 migrationLocking preview @grafana/backend-platform 2022-02-15 false false false
11 storage experimental @grafana/grafana-app-platform-squad 2022-03-17 false false false
12 correlations GA @grafana/explore-squad 2022-09-16 false false false
13 exploreContentOutline GA @grafana/explore-squad 2023-11-03 false false true
14 datasourceQueryMultiStatus experimental @grafana/plugins-platform-backend 2022-05-03 false false false
15 traceToMetrics experimental @grafana/observability-traces-and-profiling 2022-03-07 false false true
16 autoMigrateOldPanels preview @grafana/dataviz-squad 2022-06-11 false false true
17 autoMigrateGraphPanel preview @grafana/dataviz-squad 2023-12-11 false false true
18 disableAngular preview @grafana/dataviz-squad 2023-03-23 false false true
19 canvasPanelNesting experimental @grafana/dataviz-squad 2022-05-31 false false true
20 newVizTooltips preview @grafana/dataviz-squad 2023-11-03 false false true
21 scenes experimental @grafana/dashboards-squad 2022-07-07 false false true
22 disableSecretsCompatibility experimental @grafana/hosted-grafana-team 2022-07-13 false true false
23 logRequestsInstrumentedAsUnknown experimental @grafana/hosted-grafana-team 2022-06-10 false false false
24 dataConnectionsConsole GA @grafana/plugins-platform-backend 2022-06-01 false false false
25 topnav deprecated @grafana/grafana-frontend-platform 2022-06-20 false false false
26 returnToPrevious experimental @grafana/grafana-frontend-platform 2024-01-09 false false true
27 grpcServer preview @grafana/grafana-app-platform-squad 2022-09-27 false false false
28 unifiedStorage experimental @grafana/grafana-app-platform-squad 2022-12-01 true true false
29 cloudWatchCrossAccountQuerying GA @grafana/aws-datasources 2022-11-28 false false false
30 redshiftAsyncQueryDataSupport GA @grafana/aws-datasources 2022-08-27 false false false
31 athenaAsyncQueryDataSupport GA @grafana/aws-datasources 2022-08-27 false false true
32 showDashboardValidationWarnings experimental @grafana/dashboards-squad 2022-10-14 false false false
33 mysqlAnsiQuotes experimental @grafana/backend-platform 2022-10-12 false false false
34 accessControlOnCall preview @grafana/identity-access-team 2022-10-19 false false false
35 nestedFolders preview @grafana/backend-platform 2022-10-22 false false false
36 nestedFolderPicker GA @grafana/grafana-frontend-platform 2023-07-24 false false true
37 alertingBacktesting experimental @grafana/alerting-squad 2022-10-20 false false false
38 editPanelCSVDragAndDrop experimental @grafana/grafana-bi-squad 2022-12-20 false false true
39 alertingNoNormalState preview @grafana/alerting-squad 2023-01-14 false false false
40 logsContextDatasourceUi GA @grafana/observability-logs 2023-01-27 false false true
41 lokiQuerySplitting GA @grafana/observability-logs 2023-02-09 false false true
42 lokiQuerySplittingConfig experimental @grafana/observability-logs 2023-03-20 false false true
43 individualCookiePreferences experimental @grafana/backend-platform 2023-02-23 false false false
44 prometheusMetricEncyclopedia GA @grafana/observability-metrics 2023-03-07 false false true
45 influxdbBackendMigration GA @grafana/observability-metrics 2023-03-15 false false true
46 influxqlStreamingParser experimental @grafana/observability-metrics 2023-11-29 false false false
47 influxdbRunQueriesInParallel privatePreview @grafana/observability-metrics 2024-01-29 false false false
48 clientTokenRotation GA @grafana/identity-access-team 2023-03-23 false false false
49 prometheusDataplane GA @grafana/observability-metrics 2023-03-29 false false false
50 lokiMetricDataplane GA @grafana/observability-logs 2023-04-13 false false false
51 lokiLogsDataplane experimental @grafana/observability-logs 2023-07-13 false false false
52 dataplaneFrontendFallback GA @grafana/observability-metrics 2023-04-24 false false true
53 disableSSEDataplane experimental @grafana/observability-metrics 2023-04-24 false false false
54 alertStateHistoryLokiSecondary experimental @grafana/alerting-squad 2023-03-30 false false false
55 alertStateHistoryLokiPrimary experimental @grafana/alerting-squad 2023-03-30 false false false
56 alertStateHistoryLokiOnly experimental @grafana/alerting-squad 2023-03-30 false false false
57 unifiedRequestLog experimental @grafana/backend-platform 2023-03-31 false false false
58 renderAuthJWT preview @grafana/grafana-as-code 2023-04-03 false false false
59 externalServiceAuth experimental @grafana/identity-access-team 2023-04-11 true false false
60 refactorVariablesTimeRange preview @grafana/dashboards-squad 2023-06-06 false false false
61 enableElasticsearchBackendQuerying GA @grafana/observability-logs 2023-04-14 false false false
62 faroDatasourceSelector preview @grafana/app-o11y 2023-05-04 false false true
63 enableDatagridEditing preview @grafana/grafana-bi-squad 2023-04-24 false false true
64 extraThemes experimental @grafana/grafana-frontend-platform 2023-05-10 false false true
65 lokiPredefinedOperations experimental @grafana/observability-logs 2023-06-02 false false true
66 pluginsFrontendSandbox experimental @grafana/plugins-platform-backend 2023-06-05 false false true
67 dashboardEmbed experimental @grafana/grafana-as-code 2023-07-06 false false true
68 frontendSandboxMonitorOnly experimental @grafana/plugins-platform-backend 2023-07-05 false false true
69 sqlDatasourceDatabaseSelection preview @grafana/grafana-bi-squad 2023-06-06 false false true
70 lokiFormatQuery experimental @grafana/observability-logs 2023-06-21 false false true
71 cloudWatchLogsMonacoEditor GA @grafana/aws-datasources 2023-06-12 false false true
72 exploreScrollableLogsContainer experimental @grafana/observability-logs 2023-06-15 false false true
73 recordedQueriesMulti GA @grafana/observability-metrics 2023-06-14 false false false
74 pluginsDynamicAngularDetectionPatterns experimental @grafana/plugins-platform-backend 2023-06-26 false false false
75 vizAndWidgetSplit experimental @grafana/dashboards-squad 2023-06-27 false false true
76 prometheusIncrementalQueryInstrumentation experimental @grafana/observability-metrics 2023-07-05 false false true
77 logsExploreTableVisualisation experimental @grafana/observability-logs 2023-07-12 false false true
78 awsDatasourcesTempCredentials experimental @grafana/aws-datasources 2023-07-06 false false false
79 transformationsRedesign GA @grafana/observability-metrics 2023-07-12 false false true
80 mlExpressions experimental @grafana/alerting-squad 2023-07-13 false false false
81 traceQLStreaming experimental @grafana/observability-traces-and-profiling 2023-07-26 false false true
82 metricsSummary experimental @grafana/observability-traces-and-profiling 2023-08-28 false false true
83 grafanaAPIServerWithExperimentalAPIs experimental @grafana/grafana-app-platform-squad 2023-10-06 true true false
84 grafanaAPIServerEnsureKubectlAccess experimental @grafana/grafana-app-platform-squad 2023-12-06 true true false
85 featureToggleAdminPage experimental @grafana/grafana-operator-experience-squad 2023-07-18 false true false
86 awsAsyncQueryCaching GA @grafana/aws-datasources 2023-07-21 false false false
87 splitScopes deprecated @grafana/identity-access-team 2023-07-21 false true false
88 permissionsFilterRemoveSubquery experimental @grafana/backend-platform 2023-08-02 false false false
89 prometheusConfigOverhaulAuth GA @grafana/observability-metrics 2023-07-21 false false false
90 configurableSchedulerTick experimental @grafana/alerting-squad 2023-07-26 false true false
91 influxdbSqlSupport GA @grafana/observability-metrics 2023-08-02 false true false
92 alertingNoDataErrorExecution GA @grafana/alerting-squad 2023-08-15 false true false
93 angularDeprecationUI experimental @grafana/plugins-platform-backend 2023-08-29 false false true
94 dashgpt preview @grafana/dashboards-squad 2023-11-17 false false true
95 reportingRetries preview @grafana/sharing-squad 2023-08-31 false true false
96 sseGroupByDatasource experimental @grafana/observability-metrics 2023-09-07 false false false
97 libraryPanelRBAC experimental @grafana/dashboards-squad 2023-10-11 false true false
98 lokiRunQueriesInParallel privatePreview @grafana/observability-logs 2023-09-19 false false false
99 wargamesTesting experimental @grafana/hosted-grafana-team 2023-09-13 false false false
100 alertingInsights GA @grafana/alerting-squad 2023-09-14 false false true
101 externalCorePlugins experimental @grafana/plugins-platform-backend 2023-09-22 false false false
102 pluginsAPIMetrics experimental @grafana/plugins-platform-backend 2023-09-21 false false true
103 idForwarding experimental @grafana/identity-access-team 2023-09-25 false false false
104 cloudWatchWildCardDimensionValues GA @grafana/aws-datasources 2023-09-27 false false false
105 externalServiceAccounts preview @grafana/identity-access-team 2023-09-28 false false false
106 panelMonitoring experimental @grafana/dataviz-squad 2023-10-08 false false true
107 enableNativeHTTPHistogram experimental @grafana/hosted-grafana-team 2023-10-03 false false false
108 formatString preview @grafana/grafana-bi-squad 2023-10-13 false false true
109 transformationsVariableSupport preview @grafana/grafana-bi-squad 2023-10-04 false false true
110 kubernetesPlaylists experimental @grafana/grafana-app-platform-squad 2023-11-08 false true false
111 kubernetesSnapshots experimental @grafana/grafana-app-platform-squad 2023-12-04 false true false
112 kubernetesQueryServiceRewrite experimental @grafana/grafana-app-platform-squad 2024-01-28 true true false
113 cloudWatchBatchQueries preview @grafana/aws-datasources 2023-10-20 false false false
114 recoveryThreshold GA @grafana/alerting-squad 2023-10-10 false true false
115 lokiStructuredMetadata experimental @grafana/observability-logs 2023-11-16 false false false
116 teamHttpHeaders experimental @grafana/identity-access-team 2023-10-17 false false false
117 awsDatasourcesNewFormStyling preview @grafana/aws-datasources 2023-10-12 false false true
118 cachingOptimizeSerializationMemoryUsage experimental @grafana/grafana-operator-experience-squad 2023-10-12 false false false
119 panelTitleSearchInV1 experimental @grafana/backend-platform 2023-10-13 true false false
120 pluginsInstrumentationStatusSource experimental @grafana/plugins-platform-backend 2023-10-17 false false false
121 managedPluginsInstall preview @grafana/plugins-platform-backend 2023-10-18 false false false
122 prometheusPromQAIL experimental @grafana/observability-metrics 2023-10-19 false false true
123 addFieldFromCalculationStatFunctions preview @grafana/grafana-bi-squad 2023-11-03 false false true
124 alertmanagerRemoteSecondary experimental @grafana/alerting-squad 2023-10-30 false false false
125 alertmanagerRemotePrimary experimental @grafana/alerting-squad 2023-10-30 false false false
126 alertmanagerRemoteOnly experimental @grafana/alerting-squad 2023-10-30 false false false
127 annotationPermissionUpdate experimental @grafana/identity-access-team 2023-10-31 false false false
128 extractFieldsNameDeduplication experimental @grafana/grafana-bi-squad 2023-11-02 false false true
129 dashboardSceneForViewers experimental @grafana/dashboards-squad 2023-11-02 false false true
130 dashboardScene experimental @grafana/dashboards-squad 2023-11-13 false false true
131 panelFilterVariable experimental @grafana/dashboards-squad 2023-11-03 false false true
132 pdfTables preview @grafana/sharing-squad 2023-11-06 false false false
133 ssoSettingsApi experimental @grafana/identity-access-team 2023-11-08 false false false
134 canvasPanelPanZoom preview @grafana/dataviz-squad 2023-12-27 false false true
135 logsInfiniteScrolling experimental @grafana/observability-logs 2023-11-09 false false true
136 flameGraphItemCollapsing experimental @grafana/observability-traces-and-profiling 2023-11-09 false false true
137 alertingDetailsViewV2 experimental @grafana/alerting-squad 2023-11-09 false false true
138 datatrails experimental @grafana/dashboards-squad 2023-11-15 false false true
139 alertingSimplifiedRouting experimental @grafana/alerting-squad 2023-11-10 false false false
140 logRowsPopoverMenu GA @grafana/observability-logs 2023-11-16 false false true
141 pluginsSkipHostEnvVars experimental @grafana/plugins-platform-backend 2023-11-15 false false false
142 tableSharedCrosshair experimental @grafana/grafana-bi-squad 2023-12-12 false false true
143 regressionTransformation preview @grafana/grafana-bi-squad 2023-11-24 false false true
144 displayAnonymousStats GA @grafana/identity-access-team 2023-11-29 false false true
145 lokiQueryHints GA @grafana/observability-logs 2023-12-18 false false true
146 kubernetesFeatureToggles experimental @grafana/grafana-operator-experience-squad 2023-12-22 false false true
147 alertingPreviewUpgrade GA @grafana/alerting-squad 2024-01-03 false true false
148 enablePluginsTracingByDefault experimental @grafana/plugins-platform-backend 2024-01-09 false true false
149 cloudRBACRoles experimental @grafana/identity-access-team 2024-01-10 false true false
150 alertingQueryOptimization GA @grafana/alerting-squad 2024-01-10 false false false
151 newFolderPicker experimental @grafana/grafana-frontend-platform 2024-01-12 false false true
152 jitterAlertRulesWithinGroups preview @grafana/alerting-squad 2024-01-17 false true false
153 onPremToCloudMigrations experimental @grafana/grafana-operator-experience-squad 2024-01-22 false false false
154 alertingSaveStatePeriodic privatePreview @grafana/alerting-squad 2024-01-22 false false false
155 promQLScope experimental @grafana/observability-metrics 2024-01-29 false false false
156 nodeGraphDotLayout experimental @grafana/observability-traces-and-profiling 2024-01-02 false false true
157 groupToNestedTableTransformation preview @grafana/dataviz-squad 2024-02-05 false false true
158 newPDFRendering experimental @grafana/sharing-squad 2024-02-08 false false false

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@ package featuremgmt
import (
"bytes"
"encoding/csv"
"encoding/json"
"fmt"
"html/template"
"log"
@ -16,7 +17,10 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/olekukonko/tablewriter"
"github.com/stretchr/testify/require"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
featuretoggleapi "github.com/grafana/grafana/pkg/apis/featuretoggle/v0alpha1"
"github.com/grafana/grafana/pkg/services/apiserver/utils"
"github.com/grafana/grafana/pkg/services/featuremgmt/strcase"
)
@ -26,6 +30,9 @@ func TestFeatureToggleFiles(t *testing.T) {
}
t.Run("check registry constraints", func(t *testing.T) {
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)
@ -45,19 +52,105 @@ func TestFeatureToggleFiles(t *testing.T) {
if flag.AllowSelfServe && flag.Stage != FeatureStageGeneralAvailability {
t.Errorf("only allow self-serving GA toggles")
}
if flag.Created.Year() < 2021 {
t.Errorf("flag requires a reasonable created date. See: %s (%s)",
flag.Name, flag.Created.Format(time.DateOnly))
}
}
})
t.Run("all new features should have an owner", func(t *testing.T) {
for _, flag := range standardFeatureFlags {
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
t.Run("update k8s resource list", func(t *testing.T) {
created := v1.NewTime(time.Now().UTC())
resourceVersion := fmt.Sprintf("%d", created.UnixMilli())
featuresFile := "toggles_gen.json"
current := featuretoggleapi.FeatureList{
TypeMeta: v1.TypeMeta{
Kind: "FeatureList",
APIVersion: featuretoggleapi.APIVERSION,
},
}
existing := featuretoggleapi.FeatureList{}
body, err := os.ReadFile(featuresFile)
if err == nil {
_ = json.Unmarshal(body, &existing)
current.ListMeta = existing.ListMeta
}
lookup := map[string]featuretoggleapi.FeatureSpec{}
for _, flag := range standardFeatureFlags {
lookup[flag.Name] = featuretoggleapi.FeatureSpec{
Description: flag.Description,
Stage: flag.Stage.String(),
Owner: string(flag.Owner),
RequiresDevMode: flag.RequiresDevMode,
FrontendOnly: flag.FrontendOnly,
RequiresRestart: flag.RequiresRestart,
AllowSelfServe: flag.AllowSelfServe,
HideFromAdminPage: flag.HideFromAdminPage,
HideFromDocs: flag.HideFromDocs,
// EnabledVersion: ???,
}
// Replace them all
// current.Items = append(current.Items, featuretoggleapi.Feature{
// ObjectMeta: v1.ObjectMeta{
// Name: flag.Name,
// CreationTimestamp: v1.NewTime(flag.Created),
// ResourceVersion: fmt.Sprintf("%d", flag.Created.UnixMilli()),
// },
// Spec: lookup[flag.Name],
// })
// current.ListMeta.ResourceVersion = resourceVersion
}
// Check for changes in any existing values
for _, item := range existing.Items {
v, ok := lookup[item.Name]
if ok {
delete(lookup, item.Name)
a, e1 := json.Marshal(v)
b, e2 := json.Marshal(item.Spec)
if e1 != nil || e2 != nil || !bytes.Equal(a, b) {
item.ResourceVersion = resourceVersion
if item.Annotations == nil {
item.Annotations = make(map[string]string)
}
item.Annotations[utils.AnnoKeyUpdatedTimestamp] = created.String()
item.Spec = v // the current value
}
} else {
item.DeletionTimestamp = &created
fmt.Printf("mark feature as deleted")
}
current.Items = append(current.Items, item)
}
// New flags not in the existing list
for k, v := range lookup {
current.Items = append(current.Items, featuretoggleapi.Feature{
ObjectMeta: v1.ObjectMeta{
Name: k,
CreationTimestamp: created,
ResourceVersion: fmt.Sprintf("%d", created.UnixMilli()),
},
Spec: v,
})
}
out, err := json.MarshalIndent(current, "", " ")
require.NoError(t, err)
err = os.WriteFile(featuresFile, out, 0644)
require.NoError(t, err, "error writing file")
})
})
t.Run("verify files", func(t *testing.T) {
@ -85,22 +178,6 @@ func TestFeatureToggleFiles(t *testing.T) {
generateCSV(),
)
})
t.Run("check feature naming convention", func(t *testing.T) {
invalidNames := make([]string, 0)
for _, f := range standardFeatureFlags {
if legacyNames[f.Name] {
continue
}
if f.Name != strcase.ToLowerCamel(f.Name) {
invalidNames = append(invalidNames, f.Name)
}
}
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) {
@ -214,9 +291,8 @@ func generateCSV() string {
w := csv.NewWriter(&buf)
if err := w.Write([]string{
"Name",
"Stage", //flag.Stage.String(),
"Owner", //string(flag.Owner),
"Created",
"Stage", //flag.Stage.String(),
"Owner", //string(flag.Owner),
"requiresDevMode", //strconv.FormatBool(flag.RequiresDevMode),
"RequiresRestart", //strconv.FormatBool(flag.RequiresRestart),
"FrontendOnly", //strconv.FormatBool(flag.FrontendOnly),
@ -224,19 +300,11 @@ func generateCSV() string {
log.Fatalln("error writing record to csv:", err)
}
dateFormatter := func(t time.Time) string {
if t.Year() < 2020 { // fake year
return ""
}
return t.Format(time.DateOnly)
}
for _, flag := range standardFeatureFlags {
if err := w.Write([]string{
flag.Name,
flag.Stage.String(),
string(flag.Owner),
dateFormatter(flag.Created),
strconv.FormatBool(flag.RequiresDevMode),
strconv.FormatBool(flag.RequiresRestart),
strconv.FormatBool(flag.FrontendOnly),