Playlists: Remove kubernetesPlaylists flag (#104171)
This commit is contained in:
@@ -45,7 +45,6 @@ Most [generally available](https://grafana.com/docs/release-life-cycle/#general-
|
||||
| `externalCorePlugins` | Allow core plugins to be loaded as external | Yes |
|
||||
| `panelMonitoring` | Enables panel monitoring through logs and measurements | Yes |
|
||||
| `formatString` | Enable format string transformer | Yes |
|
||||
| `kubernetesPlaylists` | Use the kubernetes API in the frontend for playlists, and route /api/playlist requests to k8s | Yes |
|
||||
| `kubernetesClientDashboardsFolders` | Route the folder and dashboard service requests to k8s | Yes |
|
||||
| `recoveryThreshold` | Enables feature recovery threshold (aka hysteresis) for threshold server-side expression | Yes |
|
||||
| `lokiStructuredMetadata` | Enables the loki data source to request structured metadata from the Loki server | Yes |
|
||||
|
||||
@@ -309,11 +309,6 @@ export interface FeatureToggles {
|
||||
*/
|
||||
formatString?: boolean;
|
||||
/**
|
||||
* Use the kubernetes API in the frontend for playlists, and route /api/playlist requests to k8s
|
||||
* @default true
|
||||
*/
|
||||
kubernetesPlaylists?: boolean;
|
||||
/**
|
||||
* Routes snapshot requests from /api to the /apis endpoint
|
||||
*/
|
||||
kubernetesSnapshots?: boolean;
|
||||
|
||||
+77
-194
@@ -11,14 +11,11 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/apps/playlist/pkg/apis/playlist/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
internalplaylist "github.com/grafana/grafana/pkg/registry/apps/playlist"
|
||||
grafanaapiserver "github.com/grafana/grafana/pkg/services/apiserver"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/playlist"
|
||||
"github.com/grafana/grafana/pkg/util/errhttp"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
@@ -28,200 +25,17 @@ func (hs *HTTPServer) registerPlaylistAPI(apiRoute routing.RouteRegister) {
|
||||
// Register the actual handlers
|
||||
// TODO: remove kubernetesPlaylists feature flag
|
||||
apiRoute.Group("/playlists", func(playlistRoute routing.RouteRegister) {
|
||||
if hs.Features.IsEnabledGlobally(featuremgmt.FlagKubernetesPlaylists) {
|
||||
// Use k8s client to implement legacy API
|
||||
handler := newPlaylistK8sHandler(hs)
|
||||
playlistRoute.Get("/", handler.searchPlaylists)
|
||||
playlistRoute.Get("/:uid", handler.getPlaylist)
|
||||
playlistRoute.Get("/:uid/items", handler.getPlaylistItems)
|
||||
playlistRoute.Delete("/:uid", handler.deletePlaylist)
|
||||
playlistRoute.Put("/:uid", handler.updatePlaylist)
|
||||
playlistRoute.Post("/", handler.createPlaylist)
|
||||
} else {
|
||||
// Legacy handlers
|
||||
playlistRoute.Get("/", routing.Wrap(hs.SearchPlaylists))
|
||||
playlistRoute.Get("/:uid", hs.validateOrgPlaylist, routing.Wrap(hs.GetPlaylist))
|
||||
playlistRoute.Get("/:uid/items", hs.validateOrgPlaylist, routing.Wrap(hs.GetPlaylistItems))
|
||||
playlistRoute.Delete("/:uid", middleware.ReqEditorRole, hs.validateOrgPlaylist, routing.Wrap(hs.DeletePlaylist))
|
||||
playlistRoute.Put("/:uid", middleware.ReqEditorRole, hs.validateOrgPlaylist, routing.Wrap(hs.UpdatePlaylist))
|
||||
playlistRoute.Post("/", middleware.ReqEditorRole, routing.Wrap(hs.CreatePlaylist))
|
||||
}
|
||||
// Use k8s client to implement legacy API
|
||||
handler := newPlaylistK8sHandler(hs)
|
||||
playlistRoute.Get("/", handler.searchPlaylists)
|
||||
playlistRoute.Get("/:uid", handler.getPlaylist)
|
||||
playlistRoute.Get("/:uid/items", handler.getPlaylistItems)
|
||||
playlistRoute.Delete("/:uid", handler.deletePlaylist)
|
||||
playlistRoute.Put("/:uid", handler.updatePlaylist)
|
||||
playlistRoute.Post("/", handler.createPlaylist)
|
||||
})
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) validateOrgPlaylist(c *contextmodel.ReqContext) {
|
||||
uid := web.Params(c.Req)[":uid"]
|
||||
query := playlist.GetPlaylistByUidQuery{UID: uid, OrgId: c.GetOrgID()}
|
||||
p, err := hs.playlistService.GetWithoutItems(c.Req.Context(), &query)
|
||||
|
||||
if err != nil {
|
||||
c.JsonApiErr(404, "Playlist not found", err)
|
||||
return
|
||||
}
|
||||
|
||||
if p.OrgId == 0 {
|
||||
c.JsonApiErr(404, "Playlist not found", err)
|
||||
return
|
||||
}
|
||||
|
||||
if p.OrgId != c.GetOrgID() {
|
||||
c.JsonApiErr(403, "You are not allowed to edit/view playlist", nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// swagger:route GET /playlists playlists searchPlaylists
|
||||
//
|
||||
// Get playlists.
|
||||
//
|
||||
// Responses:
|
||||
// 200: searchPlaylistsResponse
|
||||
// 500: internalServerError
|
||||
func (hs *HTTPServer) SearchPlaylists(c *contextmodel.ReqContext) response.Response {
|
||||
query := c.Query("query")
|
||||
limit := c.QueryInt("limit")
|
||||
|
||||
if limit == 0 {
|
||||
limit = 1000
|
||||
}
|
||||
|
||||
searchQuery := playlist.GetPlaylistsQuery{
|
||||
Name: query,
|
||||
Limit: limit,
|
||||
OrgId: c.GetOrgID(),
|
||||
}
|
||||
|
||||
playlists, err := hs.playlistService.Search(c.Req.Context(), &searchQuery)
|
||||
if err != nil {
|
||||
return response.Error(http.StatusInternalServerError, "Search failed", err)
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusOK, playlists)
|
||||
}
|
||||
|
||||
// swagger:route GET /playlists/{uid} playlists getPlaylist
|
||||
//
|
||||
// Get playlist.
|
||||
//
|
||||
// Responses:
|
||||
// 200: getPlaylistResponse
|
||||
// 401: unauthorisedError
|
||||
// 403: forbiddenError
|
||||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
func (hs *HTTPServer) GetPlaylist(c *contextmodel.ReqContext) response.Response {
|
||||
uid := web.Params(c.Req)[":uid"]
|
||||
cmd := playlist.GetPlaylistByUidQuery{UID: uid, OrgId: c.GetOrgID()}
|
||||
|
||||
dto, err := hs.playlistService.Get(c.Req.Context(), &cmd)
|
||||
if err != nil {
|
||||
return response.Error(http.StatusInternalServerError, "Playlist not found", err)
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusOK, dto)
|
||||
}
|
||||
|
||||
// swagger:route GET /playlists/{uid}/items playlists getPlaylistItems
|
||||
//
|
||||
// Get playlist items.
|
||||
//
|
||||
// Responses:
|
||||
// 200: getPlaylistItemsResponse
|
||||
// 401: unauthorisedError
|
||||
// 403: forbiddenError
|
||||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
func (hs *HTTPServer) GetPlaylistItems(c *contextmodel.ReqContext) response.Response {
|
||||
uid := web.Params(c.Req)[":uid"]
|
||||
cmd := playlist.GetPlaylistByUidQuery{UID: uid, OrgId: c.GetOrgID()}
|
||||
|
||||
dto, err := hs.playlistService.Get(c.Req.Context(), &cmd)
|
||||
if err != nil {
|
||||
return response.Error(http.StatusInternalServerError, "Playlist not found", err)
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusOK, dto.Items)
|
||||
}
|
||||
|
||||
// swagger:route DELETE /playlists/{uid} playlists deletePlaylist
|
||||
//
|
||||
// Delete playlist.
|
||||
//
|
||||
// Responses:
|
||||
// 200: okResponse
|
||||
// 401: unauthorisedError
|
||||
// 403: forbiddenError
|
||||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
func (hs *HTTPServer) DeletePlaylist(c *contextmodel.ReqContext) response.Response {
|
||||
uid := web.Params(c.Req)[":uid"]
|
||||
|
||||
cmd := playlist.DeletePlaylistCommand{UID: uid, OrgId: c.GetOrgID()}
|
||||
if err := hs.playlistService.Delete(c.Req.Context(), &cmd); err != nil {
|
||||
return response.Error(http.StatusInternalServerError, "Failed to delete playlist", err)
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusOK, "")
|
||||
}
|
||||
|
||||
// swagger:route POST /playlists playlists createPlaylist
|
||||
//
|
||||
// Create playlist.
|
||||
//
|
||||
// Responses:
|
||||
// 200: createPlaylistResponse
|
||||
// 401: unauthorisedError
|
||||
// 403: forbiddenError
|
||||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
func (hs *HTTPServer) CreatePlaylist(c *contextmodel.ReqContext) response.Response {
|
||||
cmd := playlist.CreatePlaylistCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
cmd.OrgId = c.GetOrgID()
|
||||
|
||||
p, err := hs.playlistService.Create(c.Req.Context(), &cmd)
|
||||
if err != nil {
|
||||
return response.Error(http.StatusInternalServerError, "Failed to create playlist", err)
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusOK, p)
|
||||
}
|
||||
|
||||
// swagger:route PUT /playlists/{uid} playlists updatePlaylist
|
||||
//
|
||||
// Update playlist.
|
||||
//
|
||||
// Responses:
|
||||
// 200: updatePlaylistResponse
|
||||
// 401: unauthorisedError
|
||||
// 403: forbiddenError
|
||||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
func (hs *HTTPServer) UpdatePlaylist(c *contextmodel.ReqContext) response.Response {
|
||||
cmd := playlist.UpdatePlaylistCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
cmd.OrgId = c.GetOrgID()
|
||||
cmd.UID = web.Params(c.Req)[":uid"]
|
||||
|
||||
_, err := hs.playlistService.Update(c.Req.Context(), &cmd)
|
||||
if err != nil {
|
||||
return response.Error(http.StatusInternalServerError, "Failed to save playlist", err)
|
||||
}
|
||||
|
||||
dto, err := hs.playlistService.Get(c.Req.Context(), &playlist.GetPlaylistByUidQuery{
|
||||
UID: cmd.UID,
|
||||
OrgId: c.GetOrgID(),
|
||||
})
|
||||
if err != nil {
|
||||
return response.Error(http.StatusInternalServerError, "Failed to load playlist", err)
|
||||
}
|
||||
return response.JSON(http.StatusOK, dto)
|
||||
}
|
||||
|
||||
// swagger:parameters searchPlaylists
|
||||
type SearchPlaylistsParams struct {
|
||||
// in:query
|
||||
@@ -342,6 +156,15 @@ func newPlaylistK8sHandler(hs *HTTPServer) *playlistK8sHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// swagger:route GET /playlists playlists searchPlaylists
|
||||
//
|
||||
// Get playlists.
|
||||
//
|
||||
// Responses:
|
||||
// 200: searchPlaylistsResponse
|
||||
// 500: internalServerError
|
||||
//
|
||||
// Deprecated: use /apis/playlist.grafana.app/
|
||||
func (pk8s *playlistK8sHandler) searchPlaylists(c *contextmodel.ReqContext) {
|
||||
client, ok := pk8s.getClient(c)
|
||||
if !ok {
|
||||
@@ -368,6 +191,18 @@ func (pk8s *playlistK8sHandler) searchPlaylists(c *contextmodel.ReqContext) {
|
||||
c.JSON(http.StatusOK, playlists)
|
||||
}
|
||||
|
||||
// swagger:route GET /playlists/{uid} playlists getPlaylist
|
||||
//
|
||||
// Get playlist.
|
||||
//
|
||||
// Responses:
|
||||
// 200: getPlaylistResponse
|
||||
// 401: unauthorisedError
|
||||
// 403: forbiddenError
|
||||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
//
|
||||
// Deprecated: use /apis/playlist.grafana.app/
|
||||
func (pk8s *playlistK8sHandler) getPlaylist(c *contextmodel.ReqContext) {
|
||||
client, ok := pk8s.getClient(c)
|
||||
if !ok {
|
||||
@@ -382,6 +217,18 @@ func (pk8s *playlistK8sHandler) getPlaylist(c *contextmodel.ReqContext) {
|
||||
c.JSON(http.StatusOK, internalplaylist.UnstructuredToLegacyPlaylistDTO(*out))
|
||||
}
|
||||
|
||||
// swagger:route GET /playlists/{uid}/items playlists getPlaylistItems
|
||||
//
|
||||
// Get playlist items.
|
||||
//
|
||||
// Responses:
|
||||
// 200: getPlaylistItemsResponse
|
||||
// 401: unauthorisedError
|
||||
// 403: forbiddenError
|
||||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
//
|
||||
// Deprecated: use /apis/playlist.grafana.app/
|
||||
func (pk8s *playlistK8sHandler) getPlaylistItems(c *contextmodel.ReqContext) {
|
||||
client, ok := pk8s.getClient(c)
|
||||
if !ok {
|
||||
@@ -396,6 +243,18 @@ func (pk8s *playlistK8sHandler) getPlaylistItems(c *contextmodel.ReqContext) {
|
||||
c.JSON(http.StatusOK, internalplaylist.UnstructuredToLegacyPlaylistDTO(*out).Items)
|
||||
}
|
||||
|
||||
// swagger:route DELETE /playlists/{uid} playlists deletePlaylist
|
||||
//
|
||||
// Delete playlist.
|
||||
//
|
||||
// Responses:
|
||||
// 200: okResponse
|
||||
// 401: unauthorisedError
|
||||
// 403: forbiddenError
|
||||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
//
|
||||
// Deprecated: use /apis/playlist.grafana.app/
|
||||
func (pk8s *playlistK8sHandler) deletePlaylist(c *contextmodel.ReqContext) {
|
||||
client, ok := pk8s.getClient(c)
|
||||
if !ok {
|
||||
@@ -410,6 +269,18 @@ func (pk8s *playlistK8sHandler) deletePlaylist(c *contextmodel.ReqContext) {
|
||||
c.JSON(http.StatusOK, "")
|
||||
}
|
||||
|
||||
// swagger:route PUT /playlists/{uid} playlists updatePlaylist
|
||||
//
|
||||
// Update playlist.
|
||||
//
|
||||
// Responses:
|
||||
// 200: updatePlaylistResponse
|
||||
// 401: unauthorisedError
|
||||
// 403: forbiddenError
|
||||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
//
|
||||
// Deprecated: use /apis/playlist.grafana.app/
|
||||
func (pk8s *playlistK8sHandler) updatePlaylist(c *contextmodel.ReqContext) {
|
||||
client, ok := pk8s.getClient(c)
|
||||
if !ok {
|
||||
@@ -437,6 +308,18 @@ func (pk8s *playlistK8sHandler) updatePlaylist(c *contextmodel.ReqContext) {
|
||||
c.JSON(http.StatusOK, internalplaylist.UnstructuredToLegacyPlaylistDTO(*out))
|
||||
}
|
||||
|
||||
// swagger:route POST /playlists playlists createPlaylist
|
||||
//
|
||||
// Create playlist.
|
||||
//
|
||||
// Responses:
|
||||
// 200: createPlaylistResponse
|
||||
// 401: unauthorisedError
|
||||
// 403: forbiddenError
|
||||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
//
|
||||
// Deprecated: use /apis/playlist.grafana.app/
|
||||
func (pk8s *playlistK8sHandler) createPlaylist(c *contextmodel.ReqContext) {
|
||||
client, ok := pk8s.getClient(c)
|
||||
if !ok {
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"k8s.io/client-go/rest"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/storage/unified/apistore"
|
||||
"github.com/grafana/grafana/pkg/storage/unified/resource"
|
||||
@@ -153,22 +152,3 @@ func (o *StorageOptions) ApplyTo(serverConfig *genericapiserver.RecommendedConfi
|
||||
serverConfig.RESTOptionsGetter = getter
|
||||
return nil
|
||||
}
|
||||
|
||||
// EnforceFeatureToggleAfterMode1 makes sure there is a feature toggle set for resources with DualWriterMode > 1.
|
||||
// This is needed to ensure that we use the K8s client before enabling dual writing.
|
||||
func (o *StorageOptions) EnforceFeatureToggleAfterMode1(features featuremgmt.FeatureToggles) error {
|
||||
// nolint:staticcheck
|
||||
if o.StorageType != StorageTypeLegacy {
|
||||
for rg, s := range o.UnifiedStorageConfig {
|
||||
if s.DualWriterMode > 1 {
|
||||
switch rg {
|
||||
case "playlists.playlist.grafana.app":
|
||||
if !features.IsEnabledGlobally(featuremgmt.FlagKubernetesPlaylists) {
|
||||
return fmt.Errorf("feature toggle FlagKubernetesPlaylists to be set")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -4,66 +4,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
func TestStorageOptions_CheckFeatureToggle(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
StorageType StorageType
|
||||
UnifiedStorageConfig map[string]setting.UnifiedStorageConfig
|
||||
features any
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "with legacy storage",
|
||||
StorageType: StorageTypeLegacy, // nolint:staticcheck
|
||||
UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{"playlists.playlist.grafana.app": {DualWriterMode: 2}},
|
||||
features: featuremgmt.WithFeatures(),
|
||||
},
|
||||
{
|
||||
name: "with unified storage and without config for resource",
|
||||
StorageType: StorageTypeUnified,
|
||||
UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{},
|
||||
features: featuremgmt.WithFeatures(),
|
||||
},
|
||||
{
|
||||
name: "with unified storage, mode > 1 and with toggle for resource",
|
||||
StorageType: StorageTypeUnified,
|
||||
UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{"playlists.playlist.grafana.app": {DualWriterMode: 2}},
|
||||
features: featuremgmt.WithFeatures(featuremgmt.FlagKubernetesPlaylists),
|
||||
},
|
||||
{
|
||||
name: "with unified storage, mode > 1 and without toggle for resource",
|
||||
StorageType: StorageTypeUnified,
|
||||
UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{"playlists.playlist.grafana.app": {DualWriterMode: 2}},
|
||||
features: featuremgmt.WithFeatures(),
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "with unified storage and mode = 1",
|
||||
StorageType: StorageTypeUnified,
|
||||
UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{"playlists.playlist.grafana.app": {DualWriterMode: 1}},
|
||||
features: featuremgmt.WithFeatures(),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
o := &StorageOptions{
|
||||
StorageType: tt.StorageType,
|
||||
UnifiedStorageConfig: tt.UnifiedStorageConfig,
|
||||
}
|
||||
err := o.EnforceFeatureToggleAfterMode1(tt.features.(featuremgmt.FeatureToggles))
|
||||
if tt.wantErr {
|
||||
return
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStorageOptions_Validate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
@@ -271,14 +271,6 @@ func (s *service) start(ctx context.Context) error {
|
||||
return errs[0]
|
||||
}
|
||||
|
||||
// This will check that required feature toggles are enabled for more advanced storage modes
|
||||
// Any required preconditions should be hardcoded here
|
||||
if o.StorageOptions != nil {
|
||||
if err := o.StorageOptions.EnforceFeatureToggleAfterMode1(s.features); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
serverConfig := genericapiserver.NewRecommendedConfig(s.codecs)
|
||||
if err := o.ApplyTo(serverConfig); err != nil {
|
||||
return err
|
||||
|
||||
@@ -517,14 +517,6 @@ var (
|
||||
Owner: grafanaDatavizSquad,
|
||||
Expression: "true", // enabled by default
|
||||
},
|
||||
{
|
||||
Name: "kubernetesPlaylists",
|
||||
Description: "Use the kubernetes API in the frontend for playlists, and route /api/playlist requests to k8s",
|
||||
Stage: FeatureStageGeneralAvailability,
|
||||
Owner: grafanaAppPlatformSquad,
|
||||
Expression: "true",
|
||||
RequiresRestart: true, // changes the API routing
|
||||
},
|
||||
{
|
||||
Name: "kubernetesSnapshots",
|
||||
Description: "Routes snapshot requests from /api to the /apis endpoint",
|
||||
|
||||
@@ -66,7 +66,6 @@ panelMonitoring,GA,@grafana/dataviz-squad,false,false,true
|
||||
enableNativeHTTPHistogram,experimental,@grafana/grafana-backend-services-squad,false,true,false
|
||||
disableClassicHTTPHistogram,experimental,@grafana/grafana-backend-services-squad,false,true,false
|
||||
formatString,GA,@grafana/dataviz-squad,false,false,true
|
||||
kubernetesPlaylists,GA,@grafana/grafana-app-platform-squad,false,true,false
|
||||
kubernetesSnapshots,experimental,@grafana/grafana-app-platform-squad,false,true,false
|
||||
kubernetesDashboards,experimental,@grafana/grafana-app-platform-squad,false,false,true
|
||||
kubernetesClientDashboardsFolders,GA,@grafana/grafana-app-platform-squad,false,false,false
|
||||
|
||||
|
@@ -275,10 +275,6 @@ const (
|
||||
// Enable format string transformer
|
||||
FlagFormatString = "formatString"
|
||||
|
||||
// FlagKubernetesPlaylists
|
||||
// Use the kubernetes API in the frontend for playlists, and route /api/playlist requests to k8s
|
||||
FlagKubernetesPlaylists = "kubernetesPlaylists"
|
||||
|
||||
// FlagKubernetesSnapshots
|
||||
// Routes snapshot requests from /api to the /apis endpoint
|
||||
FlagKubernetesSnapshots = "kubernetesSnapshots"
|
||||
|
||||
@@ -19,7 +19,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/options"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/playlist"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/tests/apis"
|
||||
@@ -87,9 +86,6 @@ func TestIntegrationPlaylist(t *testing.T) {
|
||||
doPlaylistTests(t, apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{
|
||||
AppModeProduction: true, // do not start extra port 6443
|
||||
DisableAnonymous: true,
|
||||
EnableFeatureToggles: []string{
|
||||
featuremgmt.FlagKubernetesPlaylists, // <<< The change we are testing!
|
||||
},
|
||||
}))
|
||||
})
|
||||
|
||||
@@ -103,9 +99,6 @@ func TestIntegrationPlaylist(t *testing.T) {
|
||||
DualWriterMode: grafanarest.Mode0,
|
||||
},
|
||||
},
|
||||
EnableFeatureToggles: []string{
|
||||
featuremgmt.FlagKubernetesPlaylists, // Required so that legacy calls are also written
|
||||
},
|
||||
}))
|
||||
})
|
||||
|
||||
@@ -119,9 +112,6 @@ func TestIntegrationPlaylist(t *testing.T) {
|
||||
DualWriterMode: grafanarest.Mode1,
|
||||
},
|
||||
},
|
||||
EnableFeatureToggles: []string{
|
||||
featuremgmt.FlagKubernetesPlaylists, // Required so that legacy calls are also written
|
||||
},
|
||||
}))
|
||||
})
|
||||
|
||||
@@ -135,9 +125,6 @@ func TestIntegrationPlaylist(t *testing.T) {
|
||||
DualWriterMode: grafanarest.Mode2,
|
||||
},
|
||||
},
|
||||
EnableFeatureToggles: []string{
|
||||
featuremgmt.FlagKubernetesPlaylists, // Required so that legacy calls are also written
|
||||
},
|
||||
}))
|
||||
})
|
||||
|
||||
@@ -151,9 +138,6 @@ func TestIntegrationPlaylist(t *testing.T) {
|
||||
DualWriterMode: grafanarest.Mode3,
|
||||
},
|
||||
},
|
||||
EnableFeatureToggles: []string{
|
||||
featuremgmt.FlagKubernetesPlaylists, // Required so that legacy calls are also written
|
||||
},
|
||||
}))
|
||||
})
|
||||
|
||||
@@ -167,9 +151,6 @@ func TestIntegrationPlaylist(t *testing.T) {
|
||||
DualWriterMode: grafanarest.Mode5,
|
||||
},
|
||||
},
|
||||
EnableFeatureToggles: []string{
|
||||
featuremgmt.FlagKubernetesPlaylists, // Required so that legacy calls are also written
|
||||
},
|
||||
}))
|
||||
|
||||
client := helper.GetResourceClient(apis.ResourceClientArgs{
|
||||
@@ -205,9 +186,6 @@ func TestIntegrationPlaylist(t *testing.T) {
|
||||
AppModeProduction: false, // required for unified storage
|
||||
DisableAnonymous: true,
|
||||
APIServerStorageType: options.StorageTypeUnified, // use the entity api tables
|
||||
EnableFeatureToggles: []string{
|
||||
featuremgmt.FlagKubernetesPlaylists, // Required so that legacy calls are also written
|
||||
},
|
||||
UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{
|
||||
RESOURCEGROUP: {
|
||||
DualWriterMode: grafanarest.Mode0,
|
||||
@@ -230,9 +208,6 @@ func TestIntegrationPlaylist(t *testing.T) {
|
||||
AppModeProduction: false, // required for unified storage
|
||||
DisableAnonymous: true,
|
||||
APIServerStorageType: options.StorageTypeUnified, // use the entity api tables
|
||||
EnableFeatureToggles: []string{
|
||||
featuremgmt.FlagKubernetesPlaylists, // Required so that legacy calls are also written
|
||||
},
|
||||
UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{
|
||||
RESOURCEGROUP: {
|
||||
DualWriterMode: grafanarest.Mode2,
|
||||
@@ -246,9 +221,6 @@ func TestIntegrationPlaylist(t *testing.T) {
|
||||
AppModeProduction: false, // required for unified storage
|
||||
DisableAnonymous: true,
|
||||
APIServerStorageType: options.StorageTypeUnified, // use the entity api tables
|
||||
EnableFeatureToggles: []string{
|
||||
featuremgmt.FlagKubernetesPlaylists, // Required so that legacy calls are also written
|
||||
},
|
||||
UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{
|
||||
RESOURCEGROUP: {
|
||||
DualWriterMode: grafanarest.Mode3,
|
||||
@@ -262,9 +234,6 @@ func TestIntegrationPlaylist(t *testing.T) {
|
||||
AppModeProduction: false, // required for unified storage
|
||||
DisableAnonymous: true,
|
||||
APIServerStorageType: options.StorageTypeUnified, // use the entity api tables
|
||||
EnableFeatureToggles: []string{
|
||||
featuremgmt.FlagKubernetesPlaylists, // Required so that legacy calls are also written
|
||||
},
|
||||
UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{
|
||||
RESOURCEGROUP: {
|
||||
DualWriterMode: grafanarest.Mode5,
|
||||
@@ -286,9 +255,6 @@ func TestIntegrationPlaylist(t *testing.T) {
|
||||
DualWriterMode: grafanarest.Mode0,
|
||||
},
|
||||
},
|
||||
EnableFeatureToggles: []string{
|
||||
featuremgmt.FlagKubernetesPlaylists, // Required so that legacy calls are also written
|
||||
},
|
||||
})
|
||||
|
||||
// Clear the collection before starting (etcd)
|
||||
@@ -310,9 +276,6 @@ func TestIntegrationPlaylist(t *testing.T) {
|
||||
AppModeProduction: true,
|
||||
DisableAnonymous: true,
|
||||
APIServerStorageType: options.StorageTypeEtcd, // requires etcd running on localhost:2379
|
||||
EnableFeatureToggles: []string{
|
||||
featuremgmt.FlagKubernetesPlaylists, // Required so that legacy calls are also written
|
||||
},
|
||||
UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{
|
||||
RESOURCEGROUP: {
|
||||
DualWriterMode: grafanarest.Mode1,
|
||||
@@ -339,9 +302,6 @@ func TestIntegrationPlaylist(t *testing.T) {
|
||||
AppModeProduction: true,
|
||||
DisableAnonymous: true,
|
||||
APIServerStorageType: options.StorageTypeEtcd, // requires etcd running on localhost:2379
|
||||
EnableFeatureToggles: []string{
|
||||
featuremgmt.FlagKubernetesPlaylists, // Required so that legacy calls are also written
|
||||
},
|
||||
UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{
|
||||
RESOURCEGROUP: {
|
||||
DualWriterMode: grafanarest.Mode2,
|
||||
@@ -368,9 +328,6 @@ func TestIntegrationPlaylist(t *testing.T) {
|
||||
AppModeProduction: true,
|
||||
DisableAnonymous: true,
|
||||
APIServerStorageType: options.StorageTypeEtcd, // requires etcd running on localhost:2379
|
||||
EnableFeatureToggles: []string{
|
||||
featuremgmt.FlagKubernetesPlaylists, // Required so that legacy calls are also written
|
||||
},
|
||||
UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{
|
||||
RESOURCEGROUP: {
|
||||
DualWriterMode: grafanarest.Mode3,
|
||||
@@ -397,9 +354,6 @@ func TestIntegrationPlaylist(t *testing.T) {
|
||||
AppModeProduction: true,
|
||||
DisableAnonymous: true,
|
||||
APIServerStorageType: options.StorageTypeEtcd, // requires etcd running on localhost:2379
|
||||
EnableFeatureToggles: []string{
|
||||
featuremgmt.FlagKubernetesPlaylists, // Required so that legacy calls are also written
|
||||
},
|
||||
UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{
|
||||
RESOURCEGROUP: {
|
||||
DualWriterMode: grafanarest.Mode5,
|
||||
|
||||
Reference in New Issue
Block a user