K8s/FeatureFlags: Add an apiserver to manage feature flags (dev only) (#80501)
* add deployment registry API cloud only * update versions * add feature flag endpoints * use helpers * merge main * update AllowSelfServie and re-run code gen * fix package name * add allowselfserve flag to payload * remove config * update list api to return the full registry including states * change enabled check * fix compile error * add feature toggle and split path in frontend * changes * with status * add more status/state * add back config thing * add back config thing * merge main * merge main * now on the /current api endpoint * now on the /current api endpoint * drop frontend changes * change group name to featuretoggle (singular) * use the same settings * now with patch * more common refs * more common refs * WIP actually do the webhook * fix comment * fewer imports * registe standalone * one less file * fix singular name --------- Co-authored-by: Michael Mandrus <michael.mandrus@grafana.com>
This commit is contained in:
co-authored by
Michael Mandrus
parent
cbc84a802d
commit
41e523bde7
+7
-35
@@ -18,22 +18,20 @@ import (
|
||||
)
|
||||
|
||||
func (hs *HTTPServer) GetFeatureToggles(ctx *contextmodel.ReqContext) response.Response {
|
||||
cfg := hs.Cfg.FeatureManagement
|
||||
enabledFeatures := hs.Features.GetEnabled(ctx.Req.Context())
|
||||
|
||||
// object being returned
|
||||
dtos := make([]featuremgmt.FeatureToggleDTO, 0)
|
||||
|
||||
// loop through features an add features that should be visible to dtos
|
||||
for _, ft := range hs.featureManager.GetFlags() {
|
||||
if isFeatureHidden(ft, cfg.HiddenToggles) {
|
||||
flag := ft.Name
|
||||
if hs.featureManager.IsHiddenFromAdminPage(flag, false) {
|
||||
continue
|
||||
}
|
||||
dto := featuremgmt.FeatureToggleDTO{
|
||||
Name: ft.Name,
|
||||
Name: flag,
|
||||
Description: ft.Description,
|
||||
Enabled: enabledFeatures[ft.Name],
|
||||
ReadOnly: !isFeatureWriteable(ft, cfg.ReadOnlyToggles) || !isFeatureEditingAllowed(*hs.Cfg),
|
||||
Enabled: hs.featureManager.IsEnabled(ctx.Req.Context(), flag),
|
||||
ReadOnly: !hs.featureManager.IsEditableFromAdminPage(flag),
|
||||
}
|
||||
|
||||
dtos = append(dtos, dto)
|
||||
@@ -46,7 +44,7 @@ func (hs *HTTPServer) GetFeatureToggles(ctx *contextmodel.ReqContext) response.R
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdateFeatureToggle(ctx *contextmodel.ReqContext) response.Response {
|
||||
featureMgmtCfg := hs.Cfg.FeatureManagement
|
||||
featureMgmtCfg := hs.featureManager.Settings
|
||||
if !featureMgmtCfg.AllowEditing {
|
||||
return response.Error(http.StatusForbidden, "feature toggles are read-only", fmt.Errorf("feature toggles are configured to be read-only"))
|
||||
}
|
||||
@@ -67,7 +65,7 @@ func (hs *HTTPServer) UpdateFeatureToggle(ctx *contextmodel.ReqContext) response
|
||||
|
||||
for _, t := range cmd.FeatureToggles {
|
||||
// make sure flag exists, and only continue if flag is writeable
|
||||
if f, ok := hs.featureManager.LookupFlag(t.Name); ok && isFeatureWriteable(f, hs.Cfg.FeatureManagement.ReadOnlyToggles) {
|
||||
if hs.featureManager.IsEditableFromAdminPage(t.Name) {
|
||||
hs.log.Info("UpdateFeatureToggle: updating toggle", "toggle_name", t.Name, "enabled", t.Enabled, "username", ctx.SignedInUser.Login)
|
||||
payload.FeatureToggles[t.Name] = strconv.FormatBool(t.Enabled)
|
||||
} else {
|
||||
@@ -92,32 +90,6 @@ func (hs *HTTPServer) GetFeatureMgmtState(ctx *contextmodel.ReqContext) response
|
||||
return response.Respond(http.StatusOK, fmState)
|
||||
}
|
||||
|
||||
// isFeatureHidden returns whether a toggle should be hidden from the admin page.
|
||||
// filters out statuses Unknown, Experimental, and Private Preview
|
||||
func isFeatureHidden(flag featuremgmt.FeatureFlag, hideCfg map[string]struct{}) bool {
|
||||
if _, ok := hideCfg[flag.Name]; ok {
|
||||
return true
|
||||
}
|
||||
return flag.Stage == featuremgmt.FeatureStageUnknown || flag.Stage == featuremgmt.FeatureStageExperimental || flag.Stage == featuremgmt.FeatureStagePrivatePreview || flag.HideFromAdminPage
|
||||
}
|
||||
|
||||
// isFeatureWriteable returns whether a toggle on the admin page can be updated by the user.
|
||||
// only allows writing of GA and Deprecated toggles, and excludes the feature toggle admin page toggle
|
||||
func isFeatureWriteable(flag featuremgmt.FeatureFlag, readOnlyCfg map[string]struct{}) bool {
|
||||
if _, ok := readOnlyCfg[flag.Name]; ok {
|
||||
return false
|
||||
}
|
||||
if flag.Name == featuremgmt.FlagFeatureToggleAdminPage {
|
||||
return false
|
||||
}
|
||||
return (flag.Stage == featuremgmt.FeatureStageGeneralAvailability || flag.Stage == featuremgmt.FeatureStageDeprecated) && flag.AllowSelfServe
|
||||
}
|
||||
|
||||
// isFeatureEditingAllowed checks if the backend is properly configured to allow feature toggle changes from the UI
|
||||
func isFeatureEditingAllowed(cfg setting.Cfg) bool {
|
||||
return cfg.FeatureManagement.AllowEditing && cfg.FeatureManagement.UpdateWebhook != ""
|
||||
}
|
||||
|
||||
type UpdatePayload struct {
|
||||
FeatureToggles map[string]string `json:"feature_toggles"`
|
||||
User string `json:"user"`
|
||||
|
||||
@@ -393,9 +393,8 @@ func runGetScenario(
|
||||
) []featuremgmt.FeatureToggleDTO {
|
||||
// Set up server and send request
|
||||
cfg := setting.NewCfg()
|
||||
cfg.FeatureManagement = settings
|
||||
|
||||
fm := featuremgmt.WithFeatureManager(append([]*featuremgmt.FeatureFlag{{
|
||||
fm := featuremgmt.WithFeatureManager(settings, append([]*featuremgmt.FeatureFlag{{
|
||||
Name: featuremgmt.FlagFeatureToggleAdminPage,
|
||||
Stage: featuremgmt.FeatureStageGeneralAvailability,
|
||||
}}, features...), disabled...)
|
||||
@@ -460,9 +459,7 @@ func runSetScenario(
|
||||
) *http.Response {
|
||||
// Set up server and send request
|
||||
cfg := setting.NewCfg()
|
||||
cfg.FeatureManagement = settings
|
||||
|
||||
features := featuremgmt.WithFeatureManager(append([]*featuremgmt.FeatureFlag{{
|
||||
features := featuremgmt.WithFeatureManager(settings, append([]*featuremgmt.FeatureFlag{{
|
||||
Name: featuremgmt.FlagFeatureToggleAdminPage,
|
||||
Stage: featuremgmt.FeatureStageGeneralAvailability,
|
||||
}}, serverFeatures...), disabled...)
|
||||
|
||||
Reference in New Issue
Block a user