grafana/pkg/services/featuremgmt/models.go

139 lines
4.3 KiB
Go

package featuremgmt
import (
"bytes"
"context"
"encoding/json"
)
type FeatureToggles interface {
// IsEnabled checks if a feature is enabled for a given context.
// The settings may be per user, tenant, or globally set in the cloud
IsEnabled(ctx context.Context, flag string) bool
// IsEnabledGlobally checks if a flag is configured globally. For now, this is the same
// as the function above, however it will move to only checking flags that
// are configured by the operator and shared across all tenants.
// Use of global feature flags should be limited and careful as they require
// a full server restart for a change to take place.
IsEnabledGlobally(flag string) bool
// Get the enabled flags -- this *may* also include disabled flags (with value false)
// but it is guaranteed to have the enabled ones listed
GetEnabled(ctx context.Context) map[string]bool
}
// FeatureFlagStage indicates the quality level
type FeatureFlagStage int
const (
// FeatureStageUnknown indicates that no state is specified
FeatureStageUnknown FeatureFlagStage = iota
// FeatureStageExperimental -- Does this work for Grafana Labs?
FeatureStageExperimental
// FeatureStagePrivatePreview -- Does this work for a limited number of customers?
FeatureStagePrivatePreview
// FeatureStagePublicPreview -- Does this work for most customers?
FeatureStagePublicPreview
// FeatureStageGeneralAvailability -- Feature is available to all applicable customers
FeatureStageGeneralAvailability
// FeatureStageDeprecated the feature will be removed in the future
FeatureStageDeprecated
)
func (s FeatureFlagStage) String() string {
switch s {
case FeatureStageExperimental:
return "experimental"
case FeatureStagePrivatePreview:
return "privatePreview"
case FeatureStagePublicPreview:
return "preview"
case FeatureStageGeneralAvailability:
return "GA"
case FeatureStageDeprecated:
return "deprecated"
case FeatureStageUnknown:
}
return "unknown"
}
// MarshalJSON marshals the enum as a quoted json string
func (s FeatureFlagStage) MarshalJSON() ([]byte, error) {
buffer := bytes.NewBufferString(`"`)
buffer.WriteString(s.String())
buffer.WriteString(`"`)
return buffer.Bytes(), nil
}
// UnmarshalJSON unmarshals a quoted json string to the enum value
func (s *FeatureFlagStage) UnmarshalJSON(b []byte) error {
var j string
err := json.Unmarshal(b, &j)
if err != nil {
return err
}
switch j {
case "alpha":
fallthrough
case "experimental":
*s = FeatureStageExperimental
case "privatePreview":
*s = FeatureStagePrivatePreview
case "beta":
fallthrough
case "preview":
*s = FeatureStagePublicPreview
case "stable":
fallthrough
case "ga":
fallthrough
case "GA":
*s = FeatureStageGeneralAvailability
case "deprecated":
*s = FeatureStageDeprecated
default:
*s = FeatureStageUnknown
}
return nil
}
// These are properties about the feature, but not the current state or value for it
type FeatureFlag struct {
Name string `json:"name" yaml:"name"` // Unique name
Description string `json:"description"`
Stage FeatureFlagStage `json:"stage,omitempty"`
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)
HideFromAdminPage bool `json:"hideFromAdminPage,omitempty"` // GA, Deprecated, and PublicPreview toggles only: don't display this feature in the UI; if this is a GA toggle, add a comment with the reasoning
// CEL-GO expression. Using the value "true" will mean this is on by default
Expression string `json:"expression,omitempty"`
// Special behavior properties
RequiresDevMode bool `json:"requiresDevMode,omitempty"` // can not be enabled in production
FrontendOnly bool `json:"frontend,omitempty"` // change is only seen in the frontend
HideFromDocs bool `json:"hideFromDocs,omitempty"` // don't add the values to docs
// The server must be initialized with the value
RequiresRestart bool `json:"requiresRestart,omitempty"`
}
type FeatureToggleWebhookPayload struct {
FeatureToggles map[string]string `json:"feature_toggles"`
User string `json:"user"`
}